山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 3295 [Cqoi2011]动态逆序对(cdq分治,BIT)

 

【题目链接】

   

   http://www.lydsy.com/JudgeOnline/problem.php?id=3295

 

【题意】

   

    n个元素依次删除m个元素,求删除元素之前序列有多少个逆序对。

 

【思路】

 

    cdq分治

    这个题转化一下可以变成刚刚做过的三维偏序。

    首先有两个量:序 和 值,可以将样例写成
    x   1 2 3 4 5

    y   1 5 3 4 2

    然后因为我们要删除一些东西,所以加上时间,则样例变为

    t   1 2 3 4 5

    x   3 5 4 1 2

    y   3 2 4 1 5

    删除顺序就是按照t从大到小。我们把它看作t从小到大的插入结点。

    则我们要求的是,一个结点在t时刻插入,左边有多少个比它大,右边有多少个比它小,设这个点为(t0,x0,y0),则我们要求的就是满足

    t<t0,x<x0,y>y0

    t<t0,x>x0,y<y0

    的点数。因为具体的值对结果并无影响我们可以通过把a改成n-a+1来改变符号的方向,具体就是求满足

    t<t0,x<x0,y<(n-y0+1)

    t<t0,x<(n-x0+1),y<y0

    的点数。

  于是问题变成了刚做过的 陌上花开 问题。

  最后统计每个时间点发生之前产生的所有逆序对。   

 

【代码】

 

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #define rep(a,b,c) for(int a=b;a<=c;++a)
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 const int N =3*1e5+10;
 9 
10 void read(int &x) {
11     char c=getchar(); x=0;
12     while(!isdigit(c)) c=getchar();
13     while(isdigit(c)) x=x*10+c-'0',c=getchar();
14 }
15 
16 struct Node {
17     int a,b,c,ans;
18     bool operator<(const Node& rhs) const {
19         return a<rhs.a;
20     }
21 }q[N],T[N];
22 bool cmp(const Node& x,const Node& y)
23 {
24     return x.b<y.b||(x.b==y.b&&x.c>y.c);
25 }
26 
27 int n,m,mx,C[N],rk[N];
28 ll ans[N];
29 
30 void add(int x,int v)
31 {
32     for(;x<=mx;x+=x&-x) C[x]+=v;
33 }
34 int query(int x)
35 {
36     int res=0;
37     for(;x;x-=x&-x) res+=C[x];
38     return res;
39 }
40 
41 void solve(int l,int r)
42 {
43     if(l==r) return ;
44     int mid=(l+r)>>1;
45     solve(l,mid) , solve(mid+1,r);
46     int l1=l,l2=mid+1,i;
47     while(l2<=r) {
48         while(l1<=mid&&q[l1].b<q[l2].b) {
49             add(q[l1].c,1);
50             l1++;
51         }
52         q[l2].ans+=query(q[l2].c);
53         l2++;
54     }
55     for(i=l;i<l1;i++) add(q[i].c,-1);
56     l1=l,l2=mid+1; int now=l;
57     while(l1<=mid||l2<=r) {
58         if(l2>r||l1<=mid&&cmp(q[l1],q[l2])) T[now++]=q[l1++];
59         else T[now++]=q[l2++];
60     }
61     for(int i=l;i<=r;i++) q[i]=T[i];
62 }
63 
64 int main()
65 {
66     read(n),read(m); mx=n+5;
67     rep(i,1,n) { q[i].b=i; read(q[i].c); }
68     int a;
69     rep(i,1,m) { read(a); rk[a]=i; }
70     int sz=m;
71     rep(i,1,n) if(!rk[i]) rk[i]=++sz;
72     rep(i,1,n) q[i].a=n-rk[q[i].c]+1;
73     sort(q+1,q+n+1);
74     rep(i,1,n) q[i].b=n-q[i].b+1;
75     solve(1,n);
76     sort(q+1,q+n+1);
77     rep(i,1,n) {
78         q[i].b=n-q[i].b+1;
79         q[i].c=n-q[i].c+1;
80     }
81     solve(1,n);
82     rep(i,1,n) ans[q[i].a]=q[i].ans;
83     rep(i,1,n) ans[i]+=ans[i-1];
84     for(int i=n;i>n-m;i--)
85         printf("%lld\n",ans[i]);
86     return 0;
87 }

 

posted on 2016-03-08 20:18  hahalidaxin  阅读(604)  评论(0编辑  收藏  举报