1. 程式人生 > >P3157 [CQOI2011]動態逆序對 CDQ分治

P3157 [CQOI2011]動態逆序對 CDQ分治

Code:

#include <cstdio>
#include <algorithm>
#include <cstring>
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout) 
#define maxn 1000006
using namespace std;
int n,m,idx,place[maxn],C[maxn]; 
long long ans[maxn]; 
struct BIT{
    int lowbit(int x) { return x&(-x); }
    void add(int pos,int x){ 
        while(pos<=n) C[pos]+=x,pos+=lowbit(pos);  
    } 
    int ask(int pos){
        int sum=0;
        while(pos>0) sum+=C[pos],pos-=lowbit(pos); 
        return sum; 
    }
}tree;
struct OPT{
    int x,y,z,rnk,kind,id; 
}opt[maxn],tmp[maxn]; 
bool cmp(OPT i,OPT j)
{
    return (i.x==j.x&&i.y==j.y)?(i.rnk<j.rnk):((i.x==j.x)?i.y<j.y:i.x<j.x);    
} 
void solve(int L,int R)
{
    if(L>=R) return; 
    int mid=(L+R)>>1,tl=L-1,tr=mid; 
    for(int i=L;i<=R;++i){
        if(opt[i].rnk<=mid&&opt[i].kind==1) tree.add(opt[i].y,opt[i].z); 
        if(opt[i].rnk>mid&&opt[i].kind==2)  ans[opt[i].id]+=tree.ask(opt[i].y)*opt[i].z;  
    }
    for(int i=L;i<=R;++i) 
        if(opt[i].rnk<=mid&&opt[i].kind==1) tree.add(opt[i].y,-opt[i].z);
    for(int i=L;i<=R;++i) {
        if(opt[i].rnk<=mid) tmp[++tl]=opt[i];
        else tmp[++tr]=opt[i];
    }
    for(int i=L;i<=R;++i) opt[i]=tmp[i]; 
    solve(L,mid),solve(mid+1,R); 
}
int main(){
    //setIO("input");
    scanf("%d%d",&n,&m);
    for(int i=1,a;i<=n;++i)
    {
        scanf("%d",&a);
        opt[++idx].x=i;
        opt[idx].y=a;
        opt[idx].z=1;
        opt[idx].kind=1;
        opt[idx].rnk=idx; 
        place[a]=i; 
        tree.add(a,1); 
        ans[1]+=i-tree.ask(a); 
    }
    for(int i=1;i<=n;++i) tree.add(i,-1); 
    for(int i=1,a;i<=m;++i){
        scanf("%d",&a);
        opt[++idx].x=place[a];
        opt[idx].y=n;
        opt[idx].z=-1;
        opt[idx].kind=2;
        opt[idx].rnk=idx;
        opt[idx].id=i+1;

        opt[++idx].x=n;
        opt[idx].y=a;
        opt[idx].z=-1;
        opt[idx].kind=2;
        opt[idx].rnk=idx;
        opt[idx].id=i+1;

        opt[++idx].x=place[a];
        opt[idx].y=a;
        opt[idx].z=2;
        opt[idx].kind=2;
        opt[idx].rnk=idx;
        opt[idx].id=i+1; 

        opt[++idx].x=place[a];
        opt[idx].y=a;
        opt[idx].z=-1;
        opt[idx].kind=1; 
        opt[idx].rnk=idx;
    }
    sort(opt+1,opt+1+idx,cmp); 
    solve(1,idx); 
    for(int i=2;i<=m;++i) ans[i]+=ans[i-1]; 
    for(int i=1;i<=m;++i) printf("%lld\n",ans[i]); 
    return 0; 
}