zoukankan      html  css  js  c++  java
  • 【BZOJ】3295: [Cqoi2011]动态逆序对

    【题意】给定1~n的排列,m次操作每次删除一个数,求每次操作前的逆序对数。n<=10^5,m<=50000。

    【算法】CDQ分治+树状数组

    【题解】先树状数组求逆序对,然后统计每次删除的逆序对数。

    每个数字及其坐标构成一个二维坐标,逆序对就是两个相对位置在左上右下的点,那么删除一个点会减少的逆序对就是其左上偏序和右下偏序中的点数,转化为有操作顺序的二维平面矩阵查询和单点修改,用CDQ分治或树套树解决。

    具体细节:

    1.先加入所有加点操作(原数字必须作为最开始的操作进入CDQ分治过程),再加入前m-1个删除和询问。

    2.第一次统计右下偏序,按x轴逆序排序后CDQ分治。

    3.第二次统计左上偏序,令所有点y=n-y+1,然后按x轴正序排序后CDQ分治。

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    #define lowbit(x) (x&-x)
    using namespace std;
    int read(){
        char c;int s=0,t=1;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    const int maxn=100010;
    int n,m,ans[maxn],c[maxn],t[maxn],A[maxn],tot=0;
    struct cyc{int id,kind,qid,x,y;}a[maxn*2],b[maxn*2];
    long long ANS=0;
    void modify(int x,int k){for(int i=x;i<=n;i+=lowbit(i))c[i]+=k;}
    int query(int x){int as=0;for(int i=x;i>=1;i-=lowbit(i))as+=c[i];return as;}
    bool cmp(cyc a,cyc b){return a.x<b.x||(a.x==b.x&&a.id<b.id);}
    bool cmp2(cyc a,cyc b){return a.x>b.x||(a.x==b.x&&a.id<b.id);}
    void CDQ(int l,int r){
        if(l==r)return;
        int mid=(l+r)>>1;
        for(int i=l;i<=r;i++){
            if(a[i].id<=mid&&!a[i].kind)modify(a[i].y,a[i].qid?-1:1);
            if(a[i].id>mid&&a[i].kind)ans[a[i].qid]+=query(a[i].y);
        }
        for(int i=l;i<=r;i++)if(a[i].id<=mid&&!a[i].kind)modify(a[i].y,a[i].qid?1:-1);
        int x1=l-1,x2=mid;
        for(int i=l;i<=r;i++)if(a[i].id<=mid)b[++x1]=a[i];else b[++x2]=a[i];
        for(int i=l;i<=r;i++)a[i]=b[i];
        CDQ(l,mid);CDQ(mid+1,r);
    }    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            A[i]=read();
            t[A[i]]=i;
            modify(A[i],1);
            ANS+=i-query(A[i]);
        }
        if(m>1)printf("%lld
    ",ANS);
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)a[++tot]=(cyc){tot,0,0,i,A[i]};
        for(int i=1;i<m;i++){
            int x=read();
            a[++tot]=(cyc){tot,0,i,t[x],x};
            a[++tot]=(cyc){tot,1,i,t[x],x};
        }
        sort(a+1,a+tot+1,cmp2);
        CDQ(1,tot);
        for(int i=1;i<=tot;i++)a[i].y=n-a[i].y+1;
        sort(a+1,a+tot+1,cmp);
        CDQ(1,tot);
        for(int i=1;i<m;i++){
            ANS-=ans[i];
            printf("%lld
    ",ANS);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    能者摹形 大师窃意
    Nginx负载均衡的详细配置及使用案例详解.
    Zookeeper 4、Zookeeper开发
    nginx负载均衡
    Git:husky > npm run s precommit
    关于数据库路径 DataDirectory
    关于在VS2010 ASP.NET MVC3中使用WebService的实例
    SQLite的SQL语法
    获取IE可见高度和内容高度 记录
    转文:ASP.NET运行机制原理
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8215263.html
Copyright © 2011-2022 走看看