[BZOJ3295][Cqoi2011]动态逆序对

[BZOJ3295][Cqoi2011]动态逆序对

树套树||CDQ分治

感觉树套树更好想啊,直接无脑减就行,然而我的树套树几个月之前就打出来了,现在还没调出来……

还是CDQ好调,但是思路并不好想。我们把删除视作倒这插入,没有被删除的就视作最先插入的,于是每个操作就有了时间,位置,数值三元组,首先按时间排序,递归向下,然后在本层处理跨mid的情况:只考虑左区间对右区间的影响,至于区间内的已经递归下去了。将左右区间按位置排序,现在左边的t一定小于右边,用两个单调指针保证左边的位置小于右边(然而本题要扫两遍,第二变要保证左边位置大于右边),然后按第三维扔到权值树状数组,对于右区间查询更新答案即可。

对于本题,要查询的就是一个数左边比他大的数和右边比他小的数。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #define int long long
 6 #define ma(x) memset(x,0,sizeof(x))
 7 #define MAXN 100010
 8 using namespace std;
 9 struct al
10 {    
11     int t,s,loc,ans;
12     #define t(x) ca[x].t
13     #define s(x) ca[x].s
14     #define loc(x) ca[x].loc
15     #define ans(x) ca[x].ans
16     friend bool operator == (al a,al b)
17     {return a.t==b.t&&a.s==b.s&&a.ans==b.ans;}
18 }ca[MAXN];
19 int n,m,sum,a[MAXN],ni[MAXN];
20 int C[MAXN],bel[MAXN];
21 #define lowbit(x) ((x)&(-(x)))
22 void add(int x,int y)
23 {while(x<=n){C[x]+=y;x+=lowbit(x);}}
24 int ask(int x)
25 {int ans=0;while(x){ans+=C[x];x-=lowbit(x);}return ans;}
26 bool cmp1(al a,al b){return a.t<b.t;}
27 bool cmp2(al a,al b){return a.loc<b.loc;}
28 bool cmp3(al a,al b){return a.t>b.t;}
29 void CDQ(int l,int r)
30 {
31     if(l==r)return;
32     int mid=(l+r)>>1;
33     CDQ(l,mid),CDQ(mid+1,r);
34     sort(ca+l,ca+mid+1,cmp2);
35     sort(ca+mid+1,ca+r+1,cmp2);
36     int j=l;
37     for(int i=mid+1;i<=r;i++)
38     {    
39         while(j<=mid&&loc(j)<loc(i))add(s(j),1),j++;
40         ans(i)+=ask(n)-ask(s(i));
41     }
42     for(int i=l;i<j;i++)add(s(i),-1);
43     j=mid;
44     for(int i=r;i>mid;i--)
45     {    
46         while(j>=l&&loc(j)>loc(i))add(s(j),1),j--;
47         ans(i)+=ask(s(i)-1);
48     }
49     for(int i=mid;i>j;i--)add(s(i),-1);
50 }
51 signed main()
52 {
53 //    freopen("in.txt","r",stdin);
54 
55     cin>>n>>m;int tem=n,tt;
56     for(int i=1;i<=n;i++)
57     {cin>>s(i);loc(i)=i;bel[s(i)]=i;}
58     for(int i=1;i<=m;i++)    
59     {cin>>tt,t(bel[tt])=tem--;}
60     for(int i=1;i<=n;i++)    
61     if(!t(i))t(i)=tem--;
62     sort(ca+1,ca+n+1,cmp1);
63     CDQ(1,n);
64     sort(ca+1,ca+n+1,cmp3);
65     int eans=0;
66     for(int i=1;i<=n;i++)eans+=ans(i);
67     for(int i=1;i<=m;i++)    
68     {
69         cout<<eans<<endl;
70         eans-=ans(i);
71     }
72 }
View Code
原文地址:https://www.cnblogs.com/Al-Ca/p/11253692.html