zoukankan      html  css  js  c++  java
  • BZOJ4889:[TJOI2017]不勤劳的图书管理员

    浅谈树状数组与线段树:https://www.cnblogs.com/AKMer/p/9946944.html

    题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4889

    树状数组套线段树搞一搞就好了。

    时间复杂度:(O(nlog^2n))

    空间复杂度:(O(nlog^2n))

    代码如下:

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef pair<int,int> pii;
    #define low(i) ((i)&(-(i)))
    #define fr first
    #define sc second
     
    const int maxn=5e4+5,pps=1e9+7;
     
    int n,m,ans;
    int pos[maxn],v[maxn];
     
    int read() {
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
        for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
        return x*f;
    }
     
    struct segment_tree {
        int tot;
        pii tree[maxn*200];
        int ls[maxn*200],rs[maxn*200];
     
        void change(int p,int l,int r,int pos,int v,int cnt) {
            while(1) {
                tree[p].fr=(tree[p].fr+v)%pps;
                tree[p].sc+=cnt;if(l==r)break;
                int mid=(l+r)>>1;
                if(pos<=mid) {
                    if(!ls[p])ls[p]=++tot;
                    r=mid,p=ls[p];
                }
                else {
                    if(!rs[p])rs[p]=++tot;
                    l=mid+1,p=rs[p];
                }
            }
        }
    }T;
     
    struct TreeArray {
        int cnt1,cnt2;
        int rt[maxn],u1[maxn],u2[maxn];
     
        void change(int pos,int key1,int key2,int cnt) {
            for(int i=pos;i<=n;i+=low(i)) {
                if(!rt[i])rt[i]=++T.tot;
                T.change(rt[i],1,n,key1,key2,cnt);
            }
        }
     
        int query(int L,int R,int pos,int val,int opt) {
            if(R<=L)return 0;
            cnt1=cnt2=0;pii res;res.fr=res.sc=0;
            for(int i=L;i;i-=low(i))u1[++cnt1]=rt[i];
            for(int i=R;i;i-=low(i))u2[++cnt2]=rt[i];
            int l=1,r=n;
            while(l!=r) {
                int mid=(l+r)>>1;
                if(pos<=mid) {
                    if(opt) {
                        for(int i=1;i<=cnt1;i++) {
                            int u=T.rs[u1[i]];
                            res.fr=(res.fr-T.tree[u].fr+pps)%pps;
                            res.sc=res.sc-T.tree[u].sc;
                        }
                        for(int i=1;i<=cnt2;i++) {
                            int u=T.rs[u2[i]];
                            res.fr=(res.fr+T.tree[u].fr)%pps;
                            res.sc=res.sc+T.tree[u].sc;
                        }
                    }
                    r=mid;
                    for(int i=1;i<=cnt1;i++)u1[i]=T.ls[u1[i]];
                    for(int i=1;i<=cnt2;i++)u2[i]=T.ls[u2[i]];
                }
                else {
                    if(!opt) {
                        for(int i=1;i<=cnt1;i++) {
                            int u=T.ls[u1[i]];
                            res.fr=(res.fr-T.tree[u].fr)%pps;
                            res.sc=res.sc-T.tree[u].sc;
                        }
                        for(int i=1;i<=cnt2;i++) {
                            int u=T.ls[u2[i]];
                            res.fr=(res.fr+T.tree[u].fr)%pps;
                            res.sc=res.sc+T.tree[u].sc;
                        }
                    }
                    l=mid+1;
                    for(int i=1;i<=cnt1;i++)u1[i]=T.rs[u1[i]];
                    for(int i=1;i<=cnt2;i++)u2[i]=T.rs[u2[i]];
                }
            }
            return (res.fr+1ll*res.sc*val%pps)%pps;
        }
    }bit;
     
    int main() {
        n=read(),m=read();
        for(int i=1;i<=n;i++) {
            pos[i]=read(),v[i]=read();
            ans=(ans+bit.query(0,i-1,pos[i],v[i],1))%pps;
            bit.change(i,pos[i],v[i],1);
        }
        for(int i=1;i<=m;i++) {
            int x=read(),y=read();
            if(x>y)swap(x,y);
            ans=(ans-bit.query(x,y-1,pos[y],v[y],1)+pps)%pps;
            ans=(ans-bit.query(x,y-1,pos[x],v[x],0)+pps)%pps;
            ans=(ans+bit.query(x,y-1,pos[y],v[y],0))%pps;
            ans=(ans+bit.query(x,y-1,pos[x],v[x],1))%pps;
            if(pos[x]>pos[y])ans=(ans-v[x]-v[y]+pps)%pps;
            else if(pos[x]<pos[y])ans=(ans+v[x]+v[y])%pps;       
            bit.change(x,pos[x],-v[x],-1),bit.change(y,pos[y],-v[y],-1);
            bit.change(x,pos[y],v[y],1),bit.change(y,pos[x],v[x],1);
            swap(pos[x],pos[y]),swap(v[x],v[y]);
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Finding Palindromes POJ
    吉哥系列故事——完美队形II HDU
    Period II FZU
    生日礼物&&Supermarket
    炮兵阵地[状态压缩DP]
    最小表示法 P1368
    Period
    最长异或路径
    Luogu P5490 扫描线
    解方程
  • 原文地址:https://www.cnblogs.com/AKMer/p/10177342.html
Copyright © 2011-2022 走看看