bzoj3295: [Cqoi2011]动态逆序对

做这道题对自己很不满意啊,看起来就是很简单的两次cdq,居然搞了两中午,以后做三维偏序问题一定要明确x、y、z之间的大小关系。

这个代码写的很差,理论上应该是右边继承,被我搞成左边。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;


int n;LL s[110000];
int lowbit(int x){return x&-x;}
void add(int x,int k)
{
    while(x<=n)
    {
        s[x]+=k;
        x+=lowbit(x);
    }
}
LL getsum(int x)
{
    LL ret=0;
    while(x>=1)
    {
        ret+=s[x];
        x-=lowbit(x);
    }
    return ret;
}

//--------树状数组---------- 

struct node
{
    int x,y,z;//大小、顺序、删除时间 
    node(){z=0;}
}a[110000],b[110000],t[110000];
LL f[110000];

void cdq(int l,int r)//小,后面,没有被删除
                    //大,前面,没有被删除 == 置反,大,后面,没有被删除 
{
    if(l==r){return ;}
    
    int mid=(l+r)/2;
    cdq(l,mid);cdq(mid+1,r);
    
    int i=l,j=mid+1,p=l;
    while(i<=mid&&j<=r)
    {
        if(a[i].y>a[j].y)
        {
            f[a[i].z]+=getsum(a[i].z);
            t[p++]=a[i++];
        }
        else 
        {
            add(a[j].z,1);
            t[p++]=a[j++];
        }
    }
    while(i<=mid)
    {
        f[a[i].z]+=getsum(a[i].z);
        t[p++]=a[i++];
    }
    while(j<=r)
    {
        add(a[j].z,1);
        t[p++]=a[j++];
    }
    
    for(int j=mid+1;j<=r;j++)add(a[j].z,-1);
    for(int i=l;i<=r;i++)a[i]=t[i];
}
int main()
{
    freopen("inverse.in","r",stdin);
    freopen("inverse.out","w",stdout);
    int m,k;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&k);
        a[k].x=k;a[k].y=i;
    }
    
    for(int i=1;i<=m;i++)
        scanf("%d",&k), a[k].z=n-i+1;
    int cnt=m;
    for(int i=1;i<=n;i++)
        if(a[i].z==0)a[i].z=n-cnt, cnt++;
        
    
        
    memset(f,0,sizeof(f));
    for(int i=1;i<=n;i++)b[i]=a[i];
    for(int i=1;i<=n/2;i++)swap(a[i],a[n-i+1]);
    cdq(1,n);
    
    for(int i=1;i<=n;i++)b[i].y=n-b[i].y+1;
    for(int i=1;i<=n;i++)a[i]=b[i];
    cdq(1,n);
    
    LL sum=0;for(int i=1;i<=n;i++)sum+=f[i];
    for(int i=n;i>=n-m+1;i--)
        printf("%lld\n",sum), sum-=f[i];
    return 0;
}

 

posted @ 2017-12-28 13:01  AKCqhzdy  阅读(113)  评论(0编辑  收藏  举报