[CQOI2011]动态逆序对
Posted 蒟蒻ZJO :-)
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CQOI2011]动态逆序对相关的知识,希望对你有一定的参考价值。
P1347 - [CQOI2011]动态逆序对
Description
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
Input
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。
以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
Output
输出包含m行,依次为删除每个元素之前,逆序对的个数。
Sample Input
5 4
1
5
3
4
2
5
1
4
2
Sample Output
5
2
2
1
Hint
样例解释
(1,5,3,4,2)?(1,3,4,2)?(3,4,2)?(3,2)?(3)。
数据规模:
N<=100000 , M<=50000
把删除看成插入,将每个点赋予一个插入时间,则i的逆序对要满足的条件为:
位置在i前,值比i大,时间比i小;或者位置在i后,值比i小,时间比i小。
然后就可以用sort+CDQ+树状数组维护三维偏序,注意每个时间的答案要加上前面时间的答案。
1 #include<set> 2 #include<map> 3 #include<queue> 4 #include<stack> 5 #include<ctime> 6 #include<cmath> 7 #include<string> 8 #include<vector> 9 #include<cstdio> 10 #include<cstdlib> 11 #include<cstring> 12 #include<iostream> 13 #include<algorithm> 14 #define maxn 100010 15 using namespace std; 16 struct data{ 17 int x,y,z,ans1,ans2; 18 }f[maxn]; 19 int tree[maxn],co[maxn],LOL=0; 20 long long ans[maxn]; 21 int lowbit(int x){return x&-x;} 22 void add(int p,int v){ 23 for(int i=p;i<maxn;i+=lowbit(i)){ 24 if(co[i]!=LOL) tree[i]=0; 25 co[i]=LOL; 26 tree[i]+=v; 27 } 28 } 29 int find(int p){ 30 int ret=-0; 31 for(int i=p;i;i-=lowbit(i)) 32 if(co[i]==LOL) ret+=tree[i]; 33 return ret; 34 } 35 bool cmpcdq1(const data &a,const data &b){ 36 if(a.y!=b.y) return a.y>b.y; 37 else return a.z<b.z; 38 } 39 bool cmpcdq2(const data &a,const data &b){ 40 if(a.y!=b.y) return a.y<b.y; 41 else return a.z<b.z; 42 } 43 void CDQ1(int l,int r){ 44 if(l==r) return; 45 int mid=(l+r)>>1; 46 CDQ1(l,mid),CDQ1(mid+1,r); 47 sort(f+l,f+mid+1,cmpcdq1),sort(f+mid+1,f+r+1,cmpcdq1); 48 LOL++; 49 for(int j=mid+1,i=l;j<=r;j++){ 50 for(;f[i].y>f[j].y&&i<=mid;i++) 51 add(f[i].z,1); 52 f[j].ans1+=find(f[j].z); 53 } 54 } 55 void CDQ2(int l,int r){ 56 if(l==r) return; 57 int mid=(l+r)>>1; 58 CDQ2(l,mid),CDQ2(mid+1,r); 59 sort(f+l,f+mid+1,cmpcdq2),sort(f+mid+1,f+r+1,cmpcdq2); 60 LOL++; 61 for(int j=mid+1,i=l;j<=r;j++){ 62 for(;f[i].y<f[j].y&&i<=mid;i++) 63 add(f[i].z,1); 64 f[j].ans2+=find(f[j].z); 65 } 66 } 67 bool cmmp(const data &a,const data &b){ 68 return a.y<b.y; 69 } 70 bool cmmmp(const data &a,const data &b){ 71 return a.x<b.x; 72 } 73 bool cmmmp1(const data &a,const data &b){ 74 return a.x>b.x; 75 } 76 int main() 77 { 78 freopen("!.in","r",stdin); 79 freopen("!.out","w",stdout); 80 int n,m,sp;scanf("%d%d",&n,&m); 81 for(int i=1;i<=n;i++) 82 scanf("%d",&f[i].y),f[i].x=i; 83 sort(f+1,f+n+1,cmmp); 84 int cnt=m+1; 85 for(int i=1;i<=m;i++) 86 scanf("%d",&sp),f[sp].z=cnt,cnt--; 87 for(int i=1;i<=n;i++) 88 if(!f[i].z)f[i].z=1; 89 sort(f+1,f+n+1,cmmmp); 90 CDQ1(1,n); 91 LOL=0;memset(co,0,sizeof(co)); 92 sort(f+1,f+n+1,cmmmp1); 93 CDQ2(1,n); 94 for(int i=1;i<=n;i++) 95 ans[f[i].z]+=f[i].ans1+f[i].ans2; 96 ans[1]/=2; 97 for(int i=2;i<=m+1;i++) 98 ans[i]+=ans[i-1]; 99 for(int i=m+1;i>=2;i--) 100 printf("%lld\n",ans[i]); 101 return 0; 102 }
以上是关于[CQOI2011]动态逆序对的主要内容,如果未能解决你的问题,请参考以下文章