• 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
    ",sum), sum-=f[i];
        return 0;
    }
  • 相关阅读:
    Java学习8.31
    Java学习8.30
    Java学习8.29
    Java学习8.28
    Java学习8.27
    Java学习8.26
    242. Valid Anagram 有效的字符串
    680. Valid Palindrome II 对称字符串-可删一个字母版本
    151. Reverse Words in a String翻转一句话中的单词
    155. Min Stack 155.最小栈
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/8135151.html
Copyright © 2020-2023  润新知