bzoj3295: [Cqoi2011]动态逆序对 三维数点

为了便于考虑,把删除反序变为增加

于是就变成关于权值和位置和时间的三维数点

一波cdq一波树状数组教做人

(神TM需要longlong,80了一发)

 1 #include <bits/stdc++.h>
 2 #define mid (l+r>>1)
 3 #define ll long long
 4 using namespace std;
 5 ll n,ret,m,tem;
 6 ll tr[200001],a[200001],in[200001];
 7 bool ok[200001];
 8 struct qu
 9 {
10     ll num,pos,id,ans;
11 } q[200001],t[200001];
12 bool com(qu a,qu b)
13 {
14     return a.id<b.id;
15 }
16 void add(ll x,ll y){ for(;x<=n;x+=x&-x) tr[x]+=y;}
17 ll que(ll x){ for(ret=0;x;x-=x&-x) ret+=tr[x];return ret;}
18 void cdq(ll l,ll r)
19 {
20     if(l==r) return;
21     cdq(l,mid);cdq(mid+1,r);
22     for(ll i=l,j=l,k=mid+1;i<=r;i++)
23         if((k>r) || (j<=mid && q[j].pos<q[k].pos)) t[i]=q[j++];
24             else t[i]=q[k++];
25     ll ALL=0;
26     for(ll i=l;i<=r;i++)
27         if((q[i]=t[i]).id>mid)
28             q[i].ans+=ALL-que(q[i].num);
29         else
30             add(q[i].num,1),++ALL;
31     for(ll i=l;i<=r;i++)
32         if(q[i].id<=mid)
33             add(q[i].num,-1);
34     for(ll i=r;i>=l;i--)
35         if(q[i].id>mid)
36             q[i].ans+=que(q[i].num);
37         else
38             add(q[i].num,1);
39     for(ll i=l;i<=r;i++)
40         if(q[i].id<=mid)
41             add(q[i].num,-1);
42 }
43 int main()
44 {
45     scanf("%d%d",&n,&m);
46     for(ll i=1;i<=n;i++)
47         scanf("%d",&tem),a[tem]=i;
48     for(ll i=1;i<=m;i++)
49         scanf("%d",&in[i]),ok[in[i]]=1;
50     tem=0;
51     for(ll i=1;i<=n;i++)
52         if(!ok[i])
53             q[++tem].num=i,q[tem].pos=a[q[tem].num],q[tem].id=tem;
54     for(ll i=m;tem<=n;i--)
55         q[++tem].num=in[i],q[tem].pos=a[q[tem].num],q[tem].id=tem;
56     cdq(1,n);
57     sort(q+1,q+n+1,com);
58     for(ll i=2;i<=n;i++)
59         q[i].ans+=q[i-1].ans;
60     for(ll i=n;i>n-m;i--)
61         printf("%lld\n",q[i].ans);
62     return 0;
63 }

 

posted @ 2017-05-07 13:54  汪立超  阅读(180)  评论(0编辑  收藏  举报