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

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

排序时间,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]);
}

  

posted @ 2017-03-23 20:09  SfailSth  阅读(129)  评论(0编辑  收藏  举报