• bzoj4889 [Tjoi2017]不勤劳的图书管理员


    题目描述

    题解:

    很考验读题能力的一道题……

    首先我们知道要求的是一个类似逆序对的东西,统计时要加上两端权值。

    考虑先把初始$ans$求出来,后续操作只会改变$[l,r]$内部关系,这里分块处理。

    对于$ans$有影响的有:与端点有关的逆序对形成/破坏次数,已经中间节点与两端关系。

    块内用树状数组维护小于等于$x$的有几个,还有小于等于$x$的权值和是多少。

    再维护一下块内总权值就行了。

    代码:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 50050;
    const ll  MOD = 1000000007;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int n,m,B,bel[N],lp[400],rp[400],siz[400];
    ll sum[400];
    template<typename T>
    void Mod(T&x){if(x>=MOD)x-=MOD;}
    struct BIT
    {
        int c[N];
        void up(int x,ll d){while(x<N)Mod(c[x]+=d),x+=(x&-x);}
        ll down(int x){ll ret=0;while(x)Mod(ret+=c[x]),x-=(x&-x);return ret;}
    };
    BIT v1[400],v2[400],v0[2];
    int pos[N],val[N],pla[N];
    int main()
    {
    //    freopen("tt.in","r",stdin);
        read(n),read(m);
        B = (int)sqrt(n);
        for(int i=1;i<=n;i++)
            bel[i]=((i-1)/B)+1;
        for(int i=1;i<=bel[n];i++)
            lp[i]=(i-1)*B+1,rp[i]=min(i*B,n),siz[i] = rp[i]-lp[i]+1;
        for(int a,b,i=1;i<=n;i++)
        {
            read(a),read(b);
            v1[bel[i]].up(a,1);
            v2[bel[i]].up(a,b);
            pla[i] = a,pos[a] = i,val[a] = b,Mod(sum[bel[i]]+=b);
        }
        ll ans = 0;
        for(int i=n;i>=1;i--)
        {
            Mod(ans+=(v0[0].down(pla[i])*val[pla[i]]%MOD+v0[1].down(pla[i]))%MOD);
            v0[0].up(pla[i],1);
            v0[1].up(pla[i],val[pla[i]]);
        }
        for(int x,y,i=1;i<=m;i++)
        {
            read(x),read(y);x = pla[x],y = pla[y];
            if(x==y)
            {
                printf("%lld
    ",ans%MOD);
                continue;
            }
            if(pos[x]>pos[y])swap(x,y);
            if(x>y)Mod(ans+=MOD-(val[x]+val[y]));
            else Mod(ans+=val[x]+val[y]);
            if(bel[pos[y]]-bel[pos[x]]<=1)
            {
                for(int j=pos[x]+1;j<pos[y];j++)
                {
                    if(pla[j]>x)Mod(ans+=val[pla[j]]+val[x]);
                    else Mod(ans+=MOD-(val[pla[j]]+val[x]));
                    if(pla[j]<y)Mod(ans+=val[pla[j]]+val[y]);
                    else Mod(ans+=MOD-(val[pla[j]]+val[y]));
                }
            }else
            {
                for(int j=bel[pos[x]]+1;j<bel[pos[y]];j++)
                {
                    int nx = v1[j].down(x),ny = v1[j].down(y);
                    Mod(ans+=MOD-(val[x]*nx%MOD+val[y]*(siz[j]-ny)%MOD)%MOD);
                    Mod(ans+=(val[x]*(siz[j]-nx)%MOD+val[y]*ny%MOD)%MOD);
                    nx = v2[j].down(x),ny = v2[j].down(y);
                    Mod(ans+=(sum[j]-nx+ny+MOD)%MOD);
                    Mod(ans+=MOD-(sum[j]+nx-ny+MOD)%MOD);
                }
                for(int j=pos[x]+1;j<=rp[bel[pos[x]]];j++)
                {
                    if(pla[j]>x)Mod(ans+=val[pla[j]]+val[x]);
                    else Mod(ans+=MOD-(val[pla[j]]+val[x]));
                    if(pla[j]<y)Mod(ans+=val[pla[j]]+val[y]);
                    else Mod(ans+=MOD-(val[pla[j]]+val[y]));
                }
                for(int j=lp[bel[pos[y]]];j<=pos[y]-1;j++)
                {
                    if(pla[j]>x)Mod(ans+=val[pla[j]]+val[x]);
                    else Mod(ans+=MOD-(val[pla[j]]+val[x]));
                    if(pla[j]<y)Mod(ans+=val[pla[j]]+val[y]);
                    else Mod(ans+=MOD-(val[pla[j]]+val[y]));
                }
            }
            Mod(sum[bel[pos[x]]]+=(val[y]-val[x]+MOD)%MOD);
            Mod(sum[bel[pos[y]]]+=(val[x]-val[y]+MOD)%MOD);
            v1[bel[pos[x]]].up(x,-1);
            v1[bel[pos[y]]].up(y,-1);
            v1[bel[pos[x]]].up(y,1);
            v1[bel[pos[y]]].up(x,1);
            v2[bel[pos[x]]].up(x,-val[x]);
            v2[bel[pos[y]]].up(y,-val[y]);
            v2[bel[pos[x]]].up(y,val[y]);
            v2[bel[pos[y]]].up(x,val[x]);
            swap(pos[x],pos[y]);
            pla[pos[x]]=x;
            pla[pos[y]]=y;
            printf("%lld
    ",ans%MOD);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    thinkphp3.1.3验证码优化
    php导出数据为CSV文件DEMO
    python学习笔记十七:base64及md5编码
    linux运维笔记
    [转]如何像Python高手(Pythonista)一样编程
    用gulp清除、移动、压缩、合并、替换代码
    [蓝桥杯][2017年第八届真题]小计算器(模拟)
    [蓝桥杯][2017年第八届真题]发现环(基环树输出环)
    [蓝桥杯][2017年第八届真题]合根植物(并查集)
    省赛训练5-3(四个签到题)
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10726870.html
Copyright © 2020-2023  润新知