bzoj4889 [Tjoi2017]不勤劳的图书管理员(线段树套权值线段树)

版权声明:转载附上原文地址即可~欢迎各位神犇来虐~ https://blog.csdn.net/Icefox_zhx/article/details/79980309

相当于动态维护带权逆序对。
交换x,y位置的数,只会对他们之间的数产生影响。分类讨论即可。我写的线段树套权值线段树,卡空间,需要写垃圾回收qaq
复杂度O(nlog2n)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 50010
#define mod 1000000007
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,m,rt[N<<2],owo=0,cnt,sum,ans=0;
struct book{
    int id,v;
}a[N];
struct node{
    int cnt,lc,rc,sum;
}tr[N*256];
queue<int>rec;
inline void del(int &p){
    tr[p].lc=tr[p].rc=tr[p].cnt=tr[p].sum=0;rec.push(p);p=0;
}
inline int newp(){
    int p=0;
    if(!rec.empty()) p=rec.front(),rec.pop();
    else p=++owo;return p;
}
inline void add(int &p,int l,int r,int x,int op,int val){
    if(!p) p=newp();tr[p].cnt+=op;tr[p].sum+=op*val;tr[p].sum%=mod;
    if(l==r) return;int mid=l+r>>1;
    if(x<=mid) add(tr[p].lc,l,mid,x,op,val);
    else add(tr[p].rc,mid+1,r,x,op,val);if(!tr[p].cnt) del(p);
}
inline void ask(int p,int l,int r,int x,int y){
    if(!p) return;if(x<=l&&r<=y){cnt+=tr[p].cnt;(sum+=tr[p].sum)%=mod;return;}
    int mid=l+r>>1;if(x<=mid) ask(tr[p].lc,l,mid,x,y);
    if(y>mid) ask(tr[p].rc,mid+1,r,x,y);
}
inline void change(int p,int l,int r,int x,int y){
    if(x!=y) add(rt[p],1,n,a[x].id,-1,a[x].v);
    add(rt[p],1,n,a[y].id,1,a[y].v);if(l==r) return;int mid=l+r>>1;
    if(x<=mid) change(p<<1,l,mid,x,y);
    else change(p<<1|1,mid+1,r,x,y);
}
inline void Ask(int p,int l,int r,int x,int y,int L,int R){
    if(L>R) return;
    if(x<=l&&r<=y){ask(rt[p],1,n,L,R);return;}
    int mid=l+r>>1;if(x<=mid) Ask(p<<1,l,mid,x,y,L,R);
    if(y>mid) Ask(p<<1|1,mid+1,r,x,y,L,R);
}
int main(){
//  freopen("book5.in","r",stdin);
    n=read();m=read();
    for(int i=1;i<=n;++i){
        a[i].id=read(),a[i].v=read(),change(1,1,n,i,i);
        cnt=0;sum=0;ask(rt[1],1,n,a[i].id+1,n);
        (ans+=((ll)cnt*a[i].v%mod+sum)%mod)%=mod;
    }while(m--){
        int x=read(),y=read();if(x>y) swap(x,y);
        if(x==y){printf("%d\n",ans);continue;}
        int L=a[x].id,R=a[y].id,mn=min(L,R),mx=max(L,R);
        cnt=0;sum=0;Ask(1,1,n,x,y,mn+1,mx-1);
        ans+=(mn==L?1:-1)*(2*sum%mod+(ll)(cnt+1)*(a[x].v+a[y].v)%mod)%mod;
        ans%=mod;
        cnt=0;Ask(1,1,n,x,y,1,mn-1);(ans+=(ll)cnt*(a[y].v-a[x].v)%mod)%=mod;
        cnt=0;Ask(1,1,n,x,y,mx+1,n);(ans+=(ll)cnt*(a[x].v-a[y].v)%mod)%=mod;
        if(ans<0) ans+=mod;
        change(1,1,n,x,y);change(1,1,n,y,x);swap(a[x],a[y]);printf("%d\n",ans);
    }return 0;
}
阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页