zoukankan      html  css  js  c++  java
  • BZOJ3289: Mato的文件管理

    【传送门:BZOJ3289


    简要题意:

      给出n个数,有m个询问,每个询问输入l,r,求出l到r中的所有数通过与相邻数交换变为上升序列的交换次数


    题解:

      一开始想用在线算法做

      想不出来就用离线了

      就想到用莫队

      然后对于操作的继承,发现:

      ①在一列数的后面添加一个数,逆序对数会增加数列中比它大的数的个数。

      ②在一列数的后面删除一个数,逆序对数会减少数列中比它大的数的个数。

      ③在一列数的前面添加一个数,逆序对数会增加数列中比它小的数的个数。

      ④在一列数的前面删除一个数,逆序对数会减少数列中比它小的数的个数。

      以上抠神犇博客(因为我太懒了,发现了这些之后懒得写。。)

      设a[i]为当前l到r区间内>=i的数的个数,自然(r-l+1)-a[i]为当前l到r区间内<i的数的个数

      发现要区间修改值,原本想用线段树,后来发现树状数组差分可以做,就写了树状数组

      我的代码略丑,因为如果l<r的情况不知道怎么的就会错,所以加了几句判断

      一把辛酸泪


    参考代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    struct LS
    {
        int d,id;
    }s[51000];
    struct qn
    {
        int l,r,id;
        LL d;
    }q[51000];
    int bk[51000];
    bool cmp(qn n1,qn n2)
    {
        return bk[n1.l]==bk[n2.l]?n1.r<n2.r:bk[n1.l]<bk[n2.l];
    }
    bool cmpd(qn n1,qn n2)
    {
        return n1.id<n2.id;
    }
    bool lsd(LS n1,LS n2)
    {
        return n1.d<n2.d;
    }
    bool lsid(LS n1,LS n2)
    {
        return n1.id<n2.id;
    }
    LL a[51000];
    int lowbit(int x){return x&-x;}
    int n;
    LL getsum(int x)
    {
        LL ans=0;
        while(x!=0)
        {
            ans+=a[x];
            x-=lowbit(x);
        }
        return ans;
    }
    void change(int x,LL c)
    {
        while(x<=n)
        {
            a[x]+=c;
            x+=lowbit(x);
        }
    }
    LL t[51000];
    int main()
    {
        scanf("%d",&n);
        int block=int(sqrt(n));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&s[i].d);
            s[i].id=i;
            bk[i]=(i-1)/block+1;
        }
        sort(s+1,s+n+1,lsd);
        for(int i=1;i<=n;i++) s[i].d=i;
        sort(s+1,s+n+1,lsid);
        int m;
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id=i;
        }
        sort(q+1,q+m+1,cmp);
        int l=1,r=0;
        LL ans=0;
        memset(a,0,sizeof(a));
        for(int i=1;i<=m;i++)
        {
            while(l<q[i].l)
            {
                if(l>r){l++;continue;}
                ans-=(r-l+1)-getsum(s[l].d);
                change(1,-1);
                if(s[l].d!=n) change(s[l].d+1,1);
                l++;
            }
            while(l>q[i].l)
            {
                if(l>r+1){l--;continue;}
                ans+=(r-l+1)-getsum(s[l-1].d);
                l--;
                change(1,1);
                if(s[l].d!=n) change(s[l].d+1,-1);
            }
            while(r<q[i].r)
            {
                if(l>r+1){r++;continue;}
                ans+=getsum(s[r+1].d);
                r++;
                change(1,1);
                if(s[r].d!=n) change(s[r].d+1,-1);
            }
            while(r>q[i].r)
            {
                if(l>r){r--;continue;}
                ans-=getsum(s[r].d)-1;
                change(1,-1);
                if(s[r].d!=n) change(s[r].d+1,1);
                r--;
            }
            q[i].d=ans;
        }
        sort(q+1,q+m+1,cmpd);
        for(int i=1;i<=m;i++) printf("%lld
    ",q[i].d);
        return 0;
    }

     

  • 相关阅读:
    Redis集群启动脚本
    查看表结构
    MySQL删除冗余数据
    Java中的阶乘
    MySQL中IFNULL,ISNULL和NULLIF
    最小化安装CentOS7后要做的30件事情
    VMware的CentOS部署环境
    CentOS 上的 FirewallD 简明指南
    CentOS安装Java环境
    Linux中一些常用的很巧妙的命令
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8505903.html
Copyright © 2011-2022 走看看