BZOJ3295:[CQOI2011]动态逆序对(CDQ分治)
Description
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数
Input
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。
以下n行每行包含一个1到n之间的正整数,即初始排列。
以下m行每行一个正整数,依次为每次删除的元素。
N<=100000 M<=50000
Output
输出包含m行,依次为删除每个元素之前,逆序对的个数。
Sample Input
5 4
1
5
3
4
2
5
1
4
2
1
5
3
4
2
5
1
4
2
Sample Output
5
2
2
1
Solution
给每个被删除的元素打一个删除时间$t$,设下标为$x$,权值为$y$,那么删除一个元素后,减少的逆序对个数为:
1、$t$比它大,$x$比它小,$y$比它大。
2、$t$比它大,$x$比它大,$y$比它小。
$CDQ$统计一下就好了……
读错题把删除元素看成删除下标真的智障。
Code
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #define N (100009) 6 #define LL long long 7 using namespace std; 8 9 struct Que 10 { 11 int x,y,t; 12 bool operator < (const Que &a) const 13 { 14 return t>a.t; 15 } 16 }a[N],tmp[N]; 17 18 int n,m,c[N],q[N],ans[N],pos[N]; 19 LL sum; 20 21 inline int read() 22 { 23 int x=0,w=1; char c=getchar(); 24 while (c<'0' || c>'9') {if (c=='-') w=-1; c=getchar();} 25 while (c>='0' && c<='9') x=x*10+c-'0', c=getchar(); 26 return x*w; 27 } 28 29 void Update(int x,int k) 30 { 31 for (; x<=n; x+=(x&-x)) c[x]+=k; 32 } 33 34 int Query(int x) 35 { 36 int ans=0; 37 for (; x; x-=(x&-x)) ans+=c[x]; 38 return ans; 39 } 40 41 void CDQ1(int l,int r) 42 { 43 if (l==r) return; 44 int mid=(l+r)>>1; 45 CDQ1(l,mid); CDQ1(mid+1,r); 46 int i=l,j=mid+1,k=l-1; 47 while (i<=mid || j<=r) 48 if (j>r || i<=mid && a[i].x<a[j].x) 49 { 50 Update(a[i].y,1); 51 tmp[++k]=a[i]; ++i; 52 } 53 else 54 { 55 ans[a[j].y]+=Query(n)-Query(a[j].y); 56 tmp[++k]=a[j]; ++j; 57 } 58 for (int i=l; i<=mid; ++i) Update(a[i].y,-1); 59 for (int i=l; i<=r; ++i) a[i]=tmp[i]; 60 } 61 62 void CDQ2(int l,int r) 63 { 64 if (l==r) return; 65 int mid=(l+r)>>1; 66 CDQ2(l,mid); CDQ2(mid+1,r); 67 int i=l,j=mid+1,k=l-1; 68 while (i<=mid || j<=r) 69 if (j>r || i<=mid && a[i].x>a[j].x) 70 { 71 Update(a[i].y,1); 72 tmp[++k]=a[i]; ++i; 73 } 74 else 75 { 76 ans[a[j].y]+=Query(a[j].y-1); 77 tmp[++k]=a[j]; ++j; 78 } 79 for (int i=l; i<=mid; ++i) Update(a[i].y,-1); 80 for (int i=l; i<=r; ++i) a[i]=tmp[i]; 81 } 82 83 int main() 84 { 85 n=read(); m=read(); 86 for (int i=1; i<=n; ++i) a[i].x=i, a[i].y=read(), pos[a[i].y]=i; 87 for (int i=1; i<=m; ++i) a[pos[q[i]=read()]].t=i; 88 for (int i=1; i<=n; ++i) if (!a[i].t) a[i].t=m+1; 89 90 for (int i=1; i<=n; ++i) sum+=Query(n)-Query(a[i].y), Update(a[i].y,1); 91 for (int i=1; i<=n; ++i) Update(a[i].y,-1); 92 sort(a+1,a+n+1); CDQ1(1,n); 93 sort(a+1,a+n+1); CDQ2(1,n); 94 95 for (int i=1; i<=m; ++i) printf("%lld\n",sum), sum-=ans[q[i]]; 96 }