BZOJ3295 动态逆序对
【问题描述】
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
【输入格式】
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。
以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
【输出格式】
输出包含m行,依次为删除每个元素之前,逆序对的个数。
【输入样例】
5 4
1
5
3
4
2
5
1
4
2
【输出样例】
5
2
2
1
【样例解释】
(1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
【数据规模】
N<=100000 , M<=50000
正解:cdq分治
解题报告:这个题是让我们边修改边求逆序对,我们可以先离线处理,把删除改成插入,然后序列中所有的逆序对应该满足三个条件,我们用三个字母表示,t表示插入时间,x表示位置,y表示值,然后每一对逆序对应该是t【j】<t【i】,(x【j】<x【i】&& y【j】>y【i】) 或 (x【j】>x【i】 && y【j】<y【i】),然后就转化为经典的三维偏序,用cdq分治解决。
1 #include <iostream> 2 #include <iomanip> 3 #include <cstdlib> 4 #include <cstdio> 5 #include <cmath> 6 #include <algorithm> 7 #include <string> 8 #include <cstring> 9 #define File(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout) 10 #define RG register 11 #define ll long long 12 const int N = 105000; 13 14 using namespace std; 15 16 int gi(){ 17 char ch=getchar();int x=0; 18 while(ch<'0' || ch>'9')ch=getchar(); 19 while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();} 20 return x; 21 } 22 23 struct date{ 24 int x,s; 25 }d[N],a[N],b[N]; 26 27 int f[N],q[N],id[N],y[N],n,m,ans[N]; 28 bool vis[N]; 29 void update(int x,int s){while(x<=n){y[x]+=s;x+=x&(-x);}return;} 30 int query(int x){int s=0;while(x){s+=y[x];x-=x&(-x);}return s;} 31 32 void cdq(int l,int r){ 33 if (l>=r) return; 34 RG int i,j,k; 35 int mid=(l+r)>>1; 36 cdq(l,mid); 37 cdq(mid+1,r); 38 for (i=mid+1,j=l; i<=r; i++){ 39 while(d[j].x<d[i].x && j<=mid) update(d[j].s,1),j++; 40 ans[d[i].x]+=query(n)-query(d[i].s); 41 } 42 for (i=l; i<j; i++) update(d[i].s,-1); 43 for (i=r,j=mid; i>mid; i--){ 44 while(j>=l && d[j].x>d[i].x) update(d[j].s,1),j--; 45 ans[d[i].x]+=query(d[i].s); 46 } 47 for (i=mid; i>j; i--) update(d[i].s,-1); 48 int a1=0,b1=0; 49 for (i=l; i<=mid; i++) a[++a1]=d[i]; 50 for (i=mid+1; i<=r; i++) b[++b1]=d[i]; 51 i=1,j=1,k=l; 52 while(i<=a1 && j<=b1) if (a[i].x<b[j].x) d[k++]=a[i++]; 53 else d[k++]=b[j++]; 54 while(i<=a1) d[k++]=a[i++]; 55 while(j<=b1) d[k++]=b[j++]; 56 return; 57 } 58 59 int main(){ 60 File("3295"); 61 n=gi(),m=gi();RG int i,t=1; 62 for (i=1; i<=n; i++) f[i]=gi(),id[f[i]]=i; 63 for (i=1; i<=m; i++) q[i]=gi(),vis[q[i]]=1; 64 for (i=1; i<=n; i++) if (!vis[f[i]]) d[t++]=(date){i,f[i]}; 65 for (i=m; i>=1; i--) d[t++]=(date){id[q[i]],q[i]}; 66 cdq(1,n); 67 ll sum=0; 68 for (i=1; i<=n; i++) sum+=ans[i]; 69 for (i=1; i<=m; i++) printf("%lld\n",sum),sum-=ans[id[q[i]]]; 70 return 0; 71 }