ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[CQOI2011]动态逆序对

2021-03-02 18:32:45  阅读:205  来源: 互联网

标签:lf val int pos mid rf 动态 CQOI2011 逆序


Description

给定一个排列,每次删除一个元素,输出当前逆序对个数。

Solution

原序列的逆序对个数很好求。现在考虑删除一个数对答案的贡献。对每个元素,我们记一个它的大小 \(v\),它在序列中的位置下标 \(pos\),它被删除的时间 \(t\),对于没有被删除的元素,其删除时间设为 \(m+1\),即删除的元素个数加一。那么删除一个下标为 \(i\) 数会减少的逆序对个数就可以按下标大小分成两半来求。

\[\begin{cases} i<j \\ v_i>v_j \\ t_i<t_j \end{cases} \quad \begin{cases} i>j \\ v_i<v_j \\ t_i<t_j \end{cases} \]

容易发现都是三维偏序,直接 CDQ 分治即可。

#include<stdio.h>
#include<algorithm>
using namespace std;
#define N 100007
#define ll long long

inline int read(){
    int x=0,flag=1; char c=getchar();
    while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return flag? x:-x;
}

struct Node{
    int pos,t,val;
    ll ans;
}a[N];

ll c[N];
int n,m,D[N];

inline int lowbit(int x){return (-x)&x;}
inline void add(int x,ll v){while(x<=n)c[x]+=v,x+=lowbit(x);}
inline ll query(int x){ll ret=0;while(x)ret+=c[x],x-=lowbit(x);return ret;}

inline bool Cmp1(const Node &X,const Node &Y){return X.t!=Y.t? X.t>Y.t:X.pos>Y.pos;}
inline bool Cmp2(const Node &X,const Node &Y){return X.pos>Y.pos;}
inline bool Cmp3(const Node &X,const Node &Y){return X.val>Y.val;}

void CDQ(int lf,int rf){
    if(lf==rf) return ;
    int mid=(lf+rf)>>1;
    CDQ(lf,mid),CDQ(mid+1,rf);
    sort(a+lf,a+mid+1,Cmp2),sort(a+mid+1,a+rf+1,Cmp2);
    int i=mid+1,j=lf-1;
    for(;i<=rf;i++){
        while(j<mid&&a[j+1].pos>a[i].pos)
            ++j,add(a[j].val,1);
        a[i].ans+=query(a[i].val-1);
    }
    for(i=lf;i<=j;i++) add(a[i].val,-1);
    sort(a+lf,a+mid+1,Cmp3),sort(a+mid+1,a+rf+1,Cmp3);
    i=mid+1,j=lf-1;
    for(;i<=rf;i++){
        while(j<mid&&a[j+1].val>a[i].val)
            ++j,add(a[j].pos,1);
        a[i].ans+=query(a[i].pos-1);
    }
    for(i=lf;i<=j;i++) add(a[i].pos,-1);
}

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++) a[i].val=read(),D[a[i].val]=a[i].pos=i;
    for(int i=1;i<=m;i++) a[D[read()]].t=i;
    for(int i=1;i<=n;i++) if(!a[i].t) a[i].t=m+1;
    ll ans=0;
    for(int i=1;i<=n;i++){
        ans+=query(n-a[i].val+1);
        add(n-a[i].val+1,1);
    }
    for(int i=1;i<=n;i++) c[i]=0;
    sort(a+1,a+1+n,Cmp1),CDQ(1,n);
    sort(a+1,a+1+n,Cmp1);
    for(int i=n;i>n-m;i--){
        printf("%lld\n",ans);
        ans-=a[i].ans;
    }
}

标签:lf,val,int,pos,mid,rf,动态,CQOI2011,逆序
来源: https://www.cnblogs.com/wwlwQWQ/p/14470548.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有