P1347 - [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
Source
耒阳大视野,CQOI
主席树, 分治 ,可持久化, 分块 ,陈丹琦分治
思路{
此题是三维偏序的一道应用题;
多存一个时间戳
则问题转化为三维偏序{
一维时间戳
二维在数组中的位置
三维为值
第一维在输入预处理完
第二维 CDQ分治 第三维树状数组
或 第三维CDQ分治 第二维树状数组
目的是为了不漏掉一些相应情况
}
从后开始,化删去为插入;
求解即可
}
反思:该题真正体现了CDQ分治的离线分治的思想。需要多加体会!
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<queue> 7 #include<ctime> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 #define MAXX 100001 12 #define LL long long 13 #define RG register 14 #define lowbit(k) k&-k 15 using namespace std; 16 LL n,m,tot,T,a[MAXX],pos[MAXX],v[MAXX],tree[MAXX],col[MAXX]; 17 struct node{ 18 int d,ps,id; 19 }q[MAXX]; 20 LL ans[MAXX]; 21 // sort 22 bool Comp1(const node & x,const node & y){return x.d>y.d;} 23 bool Comp2(const node & x,const node & y){return x.ps>y.ps;} 24 // shuzhuangshuzu 25 void add(LL k){ 26 for(;k<=n;k+=lowbit(k)){ 27 if(col[k]!=T)tree[k]=0; 28 col[k]=T,tree[k]++; 29 } 30 } 31 LL sum(LL k){ 32 LL num=0; 33 for(;k;k-=lowbit(k))if(col[k]==T)num+=tree[k]; 34 return num; 35 } 36 // CDQfenzhi 37 void CDQ(int l,int r){ 38 if(l==r) return;int mid=(l+r)>>1; 39 CDQ(l,mid);CDQ(mid+1,r); 40 sort(q+l,q+mid+1,Comp1); 41 sort(q+mid+1,q+r+1,Comp1);RG int i,j;T++; 42 for(j=l,i=mid+1;i<=r;i++){ 43 for(;q[j].d>q[i].d&&j<=mid;j++) 44 add(q[j].ps); 45 ans[q[i].id]+=sum(q[i].ps); 46 }T++; 47 sort(q+l,q+mid+1,Comp2); 48 sort(q+mid+1,q+r+1,Comp2); 49 for(j=l,i=mid+1;i<=r;i++){ 50 for(;q[j].ps>q[i].ps&&j<=mid;j++){ 51 add(q[j].d); 52 } 53 ans[q[i].id]+=sum(q[i].d); 54 } 55 } 56 int main(){ 57 scanf("%lld%lld",&n,&m); 58 for(RG int i=1;i<=n;i++){ 59 int uu; 60 scanf("%d",&uu); 61 a[i]=uu;pos[uu]=i; 62 } 63 for(RG int i=1;i<=m;i++){ 64 int uu;scanf("%d",&uu); 65 uu=pos[uu];v[uu]=1; 66 q[n-i+1].d=a[uu]; 67 q[n-i+1].ps=uu; 68 q[n-i+1].id=n-i+1; 69 } 70 for(RG int i=1;i<=n;i++) if(!v[i]){ 71 q[++tot].d=a[i];// quanzhi 72 q[tot].ps=i;// weizhi 73 q[tot].id=tot;//shijin 74 } 75 CDQ(1,n);// yi jing an shi jian pai wan xu 76 for(RG int i=1;i<=n;i++) ans[i]+=ans[i-1]; 77 for(RG int i=n;i>n-m;i--) printf("%lld\n",ans[i]); 78 return 0; 79 }