[BZOJ3295] [Cqoi2011]动态逆序对 (cdq分治)

https://www.lydsy.com/JudgeOnline/problem.php?id=3295

思路:

第一种:我们可以按照删除的顺序变换成插入顺序 最先删除的就是最后插入的  然后就求逆序对啦

第二种:我们考虑删掉每个点对序列的贡献 

设当前删除了第x个元素,那么在1−x中比它大的都要减去 (x+1)N中比他小的都要减去

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 200005;
int n,m,cnt;
int a[maxn],pos[maxn],tree[maxn];
ll ans[maxn];
struct node{
    int t,x,val,type,id;
    bool friend operator<(const node u,const node v){
        if(u.x==v.x) return u.val<v.val;
        return u.x<v.x;
    }
}q[maxn],p[maxn];
int lowbit(int x){
    return x&(-x);
}
void add(int x,int val){
    while(x<=n){
        tree[x]+=val;
        x+=lowbit(x);
    }
}
int get_sum(int x){
    int res=0;
    while(x){
        res+=tree[x];
        x-=lowbit(x);
    }
    return res;
}
void cdq(int l,int r){
    if(l==r) return ;
    int m=(l+r)>>1;
    for(int i=l;i<=r;i++){
        if(q[i].t<=m) add(q[i].val,q[i].type);
        else 
            ans[q[i].id]+=q[i].type*(get_sum(n)-get_sum(q[i].val));
    }
    for(int i=l;i<=r;i++){
        if(q[i].t<=m) add(q[i].val,-q[i].type);
    }
    for(int i=r;i>=l;i--){
        if(q[i].t<=m) add(q[i].val,q[i].type);
        else ans[q[i].id]+=q[i].type*get_sum(q[i].val-1);
    }
    for(int i=l;i<=r;i++){
        if(q[i].t<=m) add(q[i].val,-q[i].type);
    }
    int q1=l;
    int q2=m+1;
    for(int i=l;i<=r;i++){
        if(q[i].t<=m) p[q1++]=q[i];
        else p[q2++]=q[i];
    }
    for(int i=l;i<=r;i++)
        q[i]=p[i];
    cdq(l,m);
    cdq(m+1,r);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        pos[a[i]]=i;
        q[++cnt]=node({cnt,i,a[i],1,0});
    }
    for(int i=1;i<=m;i++){
        int x;
        scanf("%d",&x);
        q[++cnt]=node({cnt,pos[x],x,-1,i});
    }
    sort(q+1,q+1+cnt);
    cdq(1,cnt);
    for(int i=1;i<=m;i++){
        printf("%lld\n",ans[i-1]);
        ans[i]+=ans[i-1];
    }
    return 0;
}
View Code

 

posted @ 2019-09-10 21:39  MengX  阅读(165)  评论(0编辑  收藏  举报

梦想不是空想