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

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 }
posted @ 2019-03-06 08:54  Refun  阅读(204)  评论(0编辑  收藏  举报