zoukankan      html  css  js  c++  java
  • 【BZOJ3744】Gty的妹子序列-序列分块+树状数组

    测试地址:Gty的妹子序列
    做法:本题需要用到序列分块+树状数组。
    求区间逆序对数,我们知道可以用莫队算法+树状数组来做离线做法,但是这题强制在线,我们应该怎么办呢?
    还是考虑分块,将序列分成n块,每块有n个元素。我们需要尽可能快的处理出尽可能多的区间内的逆序对数,这样可以有助于我们进行下一步操作。令num(l,r)为区间[l,r]的答案,我们可以枚举每个块,对每个块的左端点i,处理出所有num(i,j)(j>i),用树状数组处理的话,对于每个块都是O(nlogn)的,那么总时间复杂度就是O(nnlogn)。同样地,对每个块的右端点i,处理出所有num(j,i)(j<i)
    有了这些东西,我们应该怎么继续往下做呢?对于一个询问[l,r],找到l,r所在的块,假定它们分别为c,d(当然有可能c=d)。令lft(i),rht(i)为第i块的左右端点,我们计算num(lft(c),r)+num(l,rht(d))num(lft(c),rht(d)),注意到这个结果等于num(l,r)再减去一端在[lft(c),l1],一端在[r+1,rht(d)]中的逆序对数。因为这两个区间的长度都不超过n,那么只需要暴力O(nlogn)处理出多减去的值,然后加回去即可。
    那么我们就解决了这一道题,总时间复杂度为O(nnlogn)
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    int n,m,blocksiz,block[50010],blockhead[230],blocktail[230],maxb,tot,a[50010];
    int lft[230][50010],rht[230][50010],sum[50010]={0};
    struct forsort
    {
        int id,val;
    }f[50010];
    
    bool cmp(forsort a,forsort b)
    {
        return a.val<b.val;
    }
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    
    void BITadd(int x,int c)
    {
        for(int i=x;i<=n;i+=lowbit(i))
            sum[i]+=c;
    }
    
    int BITsum(int x)
    {
        int s=0;
        for(int i=x;i;i-=lowbit(i))
            s+=sum[i];
        return s;
    }
    
    int main()
    {
        scanf("%d",&n);
        blocksiz=(int)sqrt(n);
        for(int i=1;i<=n;i++)
        {
            block[i]=(i-1)/blocksiz;
            if (i==1||block[i]!=block[i-1])
            {
                blockhead[block[i]]=i;
                if (i>1) blocktail[block[i-1]]=i-1;
            }
            scanf("%d",&f[i].val);
            f[i].id=i;
        }
        maxb=(n-1)/blocksiz;
        blocktail[maxb]=n;
    
        sort(f+1,f+n+1,cmp);
        tot=0;
        for(int i=1;i<=n;i++)
        {
            if (i==1||f[i].val!=f[i-1].val) tot++;
            a[f[i].id]=tot;
        }
    
        for(int i=0;i<=maxb;i++)
        {
            memset(sum,0,sizeof(sum));
            lft[i][blockhead[i]]=0;
            BITadd(a[blockhead[i]],1);
            for(int j=blockhead[i]+1;j<=n;j++)
            {
                lft[i][j]=lft[i][j-1]+BITsum(n)-BITsum(a[j]);
                BITadd(a[j],1);
            }
            memset(sum,0,sizeof(sum));
            rht[i][blocktail[i]]=0;
            BITadd(a[blocktail[i]],1);
            for(int j=blocktail[i]-1;j;j--)
            {
                rht[i][j]=rht[i][j+1]+BITsum(a[j]-1);
                BITadd(a[j],1);
            }
        }
    
        scanf("%d",&m);
        int lastans=0;
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=m;i++)
        {
            int l,r,ans;
            scanf("%d%d",&l,&r);
            l^=lastans,r^=lastans;
            ans=lft[block[l]][r]+rht[block[r]][l]-lft[block[l]][blocktail[block[r]]];
            for(int j=r+1;j<=blocktail[block[r]];j++)
                BITadd(a[j],1);
            for(int j=blockhead[block[l]];j<l;j++)
                ans+=BITsum(a[j]-1);
            for(int j=r+1;j<=blocktail[block[r]];j++)
                BITadd(a[j],-1);
            printf("%d
    ",ans);
            lastans=ans;
        }
    
        return 0;
    }
  • 相关阅读:
    70.BOM
    69.捕获错误try catch
    68.键盘事件
    523. Continuous Subarray Sum
    901. Online Stock Span
    547. Friend Circles
    162. Find Peak Element
    1008. Construct Binary Search Tree from Preorder Traversal
    889. Construct Binary Tree from Preorder and Postorder Traversal
    106. Construct Binary Tree from Inorder and Postorder Traversal
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793521.html
Copyright © 2011-2022 走看看