您的位置:首页 > 其它

BZOJ 3295 [Cqoi2011]动态逆序对 ——CDQ分治

2017-03-23 20:09 429 查看

时间、位置、数字为三个属性。

排序时间,CDQ位置,树状数组处理数字即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define ll long long
#define maxn 100005
int a[maxn],q[maxn],n,m,pos[maxn],del[maxn];
struct Event{
int t;//时间
int x;//加入的数
int y;//加入的位置
}b[maxn];
struct Bit_Tree{
int x[maxn];
void add(int i,int f)
{
for (;i<maxn;i+=i&(-i)) x[i]+=f;
}
int gs(int i)
{
int ret=0;
for (;i;i-=i&(-i)) ret+=x[i];
return ret;
}
}BT;

bool cmp1(Event a,Event b) {return a.t<b.t;}

bool cmp2(Event a,Event b) {return a.y<b.y;}

bool cmp3(Event a,Event b) {return a.y>b.y;}

ll ans[maxn];

void CDQ(int l,int r,int flag)
{
if (l==r) return ;
int mid=l+r>>1;
CDQ(l,mid,flag); CDQ(mid+1,r,flag);
int pl=l;
if (flag) F(i,mid+1,r)
{
while (b[pl].y<b[i].y&&pl<=mid) BT.add(b[pl++].x,1);
int tmp=BT.gs(n)-BT.gs(b[i].x-1);
ans[b[i].t]+=tmp;
}
else F(i,mid+1,r)
{
while (b[pl].y>b[i].y&&pl<=mid) BT.add(b[pl++].x,1);
int tmp=BT.gs(b[i].x-1);
ans[b[i].t]+=tmp;
}
F(i,l,pl-1) BT.add(b[i].x,-1);
sort(b+l,b+r+1,flag?cmp2:cmp3);
}

int main()
{
scanf("%d%d",&n,&m);
F(i,1,n) scanf("%d",&a[i]),pos[a[i]]=i;
F(i,1,m)
{
scanf("%d",&q[i]);
del[q[i]]=1;
b[i].t=n-i+1;
b[i].x=q[i];
b[i].y=pos[q[i]];
}
int now=m;
F(i,1,n)
if (!del[i])
{
b[++now].t=n-now+1;
b[now].x=i;
b[now].y=pos[i];
}
sort(b+1,b+n+1,cmp1);
CDQ(1,n,1);
sort(b+1,b+n+1,cmp1);
CDQ(1,n,0);
F(i,2,n) ans[i]+=ans[i-1];
D(i,n,n-m+1) printf("%lld\n",ans[i]);
}

  

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: