首页 > 代码库 > bzoj 3295 动态逆序对 CDQ分支

bzoj 3295 动态逆序对 CDQ分支

       容易看出ans[i]=ans[i-1]-q[i],q[i]为删去第i个数减少的逆序对。

       先用树状数组算出最开始的逆序对,预处理出每个数前边比它大的和后边比它小的,就求出了q[i]的初始值。

       设b[i]是第i个删除的数,pos[i]为i在数列里的位置。

       对q[i]产生影响的是   1. j<i,pos[b[j]]<pos[b[i]],b[j]>b[i].  2.j<i,pos[b[j]]>pos[b[i]],b[j]<b[i].

       因为是三维的,所以我们套一层cdq。

       

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define int long long
 6 #define N 100005
 7 using namespace std;
 8 int n,m;
 9 int a[N],b[N],d[N];
10 int c[N];
11 int ans[N];int p[N];
12 int qur(int x)
13 {
14     int tp=0;
15     for(int i=x;i;i-=(i&-i))tp+=c[i];
16     return tp;
17 }
18 void add(int x,int z)
19 {
20     for(int i=x;i<=n;i+=(i&-i))c[i]+=z;
21     return ;
22 }
23 int tmp[N];int q[N];
24 bool cmp(int x,int y)
25 {
26     return p[x]<p[y];
27 }
28 void solve(int l,int r)
29 {
30     if(l==r)return ;
31     int mid=(l+r)>>1;
32     int cnt=0;
33     for(int i=l;i<=r;i++)tmp[++cnt]=b[i];
34     sort(tmp+1,tmp+cnt+1,cmp);
35     for(int i=1;i<=cnt;i++)
36     {
37         if(d[tmp[i]]<=mid)add(tmp[i],1);
38         else q[tmp[i]]-=qur(n)-qur(tmp[i]);
39     }
40     for(int i=1;i<=cnt;i++)if(d[tmp[i]]<=mid)add(tmp[i],-1);
41     for(int i=cnt;i>=1;i--)
42     {
43         if(d[tmp[i]]<=mid)add(tmp[i],1);
44         else q[tmp[i]]-=qur(tmp[i]);
45     }
46     for(int i=1;i<=cnt;i++)if(d[tmp[i]]<=mid)add(tmp[i],-1);
47     solve(l,mid);solve(mid+1,r);
48     return ;
49 }
50 signed main()
51 {
52     scanf("%lld%lld",&n,&m);
53     for(int i=1;i<=n;i++)scanf("%lld",&a[i]),p[a[i]]=i;
54     for(int i=1;i<=m;i++)scanf("%lld",&b[i]),d[b[i]]=i;
55     for(int i=1;i<=n;i++)
56     {
57         int tp=qur(n)-qur(a[i]);
58         ans[0]+=tp;
59         q[a[i]]+=tp;
60         add(a[i],1);
61     }
62     memset(c,0,sizeof(c));
63     for(int i=n;i>=1;i--)
64     {
65         int tp=qur(a[i]);
66         q[a[i]]+=tp;
67         add(a[i],1);
68     }
69     memset(c,0,sizeof(c));
70     solve(1,m);
71     for(int i=1;i<m;i++)ans[i]=ans[i-1]-q[b[i]];
72     for(int i=0;i<m;i++)printf("%lld\n",ans[i]);
73     return 0;
74 }

 

bzoj 3295 动态逆序对 CDQ分支