BZOJ 3295 [CQOI2011]动态逆序对 (三维偏序CDQ+树状数组)

题目大意:

题面传送门

还是一道三维偏序题

每次操作都可以看成这样一个三元组 $<x,w,t>$ ,操作的位置,权值,修改时间

一开始的序列看成n次插入操作

我们先求出不删除时的逆序对总数量,再统计每次删除元素时,减少的逆序对数量

然后就是三维偏序裸题了吧,第一维时间,第二维操作位置,第三维权值,用树状数组维护即可

由于逆序对可以在被删除元素的前面或者后面,所以在归并时需要正反遍历各统计一次

 1 #include <vector>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define N1 150100
 6 #define ll long long
 7 #define dd double
 8 #define inf 0x3f3f3f3f3f3f3f3fll
 9 using namespace std;
10 
11 int gint()
12 {
13     int ret=0,fh=1;char c=getchar();
14     while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();}
15     while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();}
16     return ret*fh;
17 }
18 int n,m,nn,K;
19 
20 struct node{
21 int p,t,x,w,ans;
22 }a[N1],tmp[N1];
23 
24 struct BIT{
25 int s[N1];
26 void update(int x,int w){for(int i=x;i<=n;i+=(i&(-i))) s[i]+=w;}
27 int query(int x){int ans=0; for(int i=x;i;i-=(i&(-i))) ans+=s[i]; return ans;}
28 }b;
29 
30 int que[N1],tl;
31 void CDQ(int L,int R)
32 {
33     if(R-L<=1) return;
34     int M=(L+R)>>1;
35     CDQ(L,M); CDQ(M,R);
36     int i,j,x,cnt;
37     
38     i=M-1,j=R-1,cnt=0;
39     while(i>=L&&j>=M)
40     {
41         if(a[i].x>a[j].x){
42             b.update(a[i].w,a[i].p);
43             que[++tl]=i; i--; 
44         }else{
45             if(a[j].p==-1) a[j].ans+=b.query(a[j].w-1);
46             j--; 
47         }
48     }
49     while(i>=L) {i--;}
50     while(j>=M) {if(a[j].p==-1) a[j].ans+=b.query(a[j].w-1); j--;}
51     while(tl) {x=que[tl--]; b.update(a[x].w,-a[x].p);}
52     
53     i=L,j=M,cnt=0;
54     while(i<M&&j<R)
55     {
56         if(a[i].x<a[j].x){
57             b.update(a[i].w,a[i].p);
58             que[++tl]=i; tmp[++cnt]=a[i]; i++; 
59         }else{
60             if(a[j].p==-1) a[j].ans+=b.query(n)-b.query(a[j].w);
61             tmp[++cnt]=a[j]; j++;
62         }
63     }
64     while(i<M) {tmp[++cnt]=a[i]; i++;}
65     while(j<R) {if(a[j].p==-1) a[j].ans+=b.query(n)-b.query(a[j].w); tmp[++cnt]=a[j]; j++;}
66     while(tl) {x=que[tl--]; b.update(a[x].w,-a[x].p);}
67     
68     for(i=L;i<R;i++) a[i]=tmp[i-L+1];
69 }
70 int cmp(node s1,node s2){
71     if(s1.p!=s2.p) return s1.p>s2.p;
72     return s1.t<s2.t;}
73 int pos[N1];
74 
75 int main()
76 {
77     scanf("%d%d",&n,&m);
78     int i; ll ans=0; nn=n+m;
79     for(i=1;i<=n;i++) a[i].w=gint(),a[i].x=i,a[i].p=1,a[i].t=i,pos[a[i].w]=i;
80     for(i=n;i>=1;i--) ans+=b.query(a[i].w),b.update(a[i].w,1);
81     memset(b.s,0,sizeof(b.s));
82     for(i=n+1;i<=n+m;i++) a[i].w=gint(),a[i].x=pos[a[i].w],a[i].p=-1,a[i].t=i;
83     CDQ(1,n+m+1);
84     sort(a+1,a+n+m+1,cmp);
85     for(i=n+1;i<=n+m;i++)
86     {
87         printf("%lld\n",ans);
88         ans-=a[i].ans;
89     }
90     return 0;
91 }

 

posted @ 2018-12-31 20:03  guapisolo  阅读(231)  评论(0编辑  收藏  举报