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\n",ans);
    }
    return 0;
}
posted @ 2018-12-26 08:57  AKMer  阅读(175)  评论(0编辑  收藏  举报