bzoj4889: [Tjoi2017]不勤劳的图书管理员(树套树)

传送门

 

据说正解线段树套平衡树

然而网上参考(抄)了一个树状数组套动态开点线段树的

思路比较清楚,看代码应该就明白了

  1 //minamoto
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #define ll long long
  6 using namespace std;
  7 const int N=50005,mod=1e9+7;
  8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
  9 char buf[1<<21],*p1=buf,*p2=buf;
 10 inline int read(){
 11     #define num ch-'0'
 12     char ch;bool flag=0;int res;
 13     while(!isdigit(ch=getc()))
 14     (ch=='-')&&(flag=true);
 15     for(res=num;isdigit(ch=getc());res=res*10+num);
 16     (flag)&&(res=-res);
 17     #undef num
 18     return res;
 19 }
 20 char sr[1<<21],z[20];int C=-1,Z;
 21 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
 22 inline void print(ll x){
 23     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
 24     while(z[++Z]=x%10+48,x/=10);
 25     while(sr[++C]=z[Z],--Z);sr[++C]='\n';
 26 }
 27 int n,m,a[N],b[N],c[N],cntt[N];
 28 ll ans;
 29 inline void add(int x,int y){
 30     for(;x<=n;x+=x&-x) c[x]+=y,++cntt[x];
 31 }
 32 inline ll sum_v(int x){
 33     ll res=0;
 34     for(;x;x-=x&-x) res+=c[x];return res;
 35 }
 36 inline ll sum_cnt(int x){
 37     ll res=0;
 38     for(;x;x-=x&-x) res+=cntt[x];return res;
 39 }
 40 int tot,rt[N],cnt[N<<8],L[N<<8],R[N<<8];ll v[N<<8];
 41 void insert(int &p,int l,int r,int x,int k,int t){
 42     if(!p) p=++tot;v[p]+=k,cnt[p]+=t;
 43     if(l==r) return;int mid=l+r>>1;
 44     if(x<=mid) insert(L[p],l,mid,x,k,t);
 45     else insert(R[p],mid+1,r,x,k,t);
 46 }
 47 inline void add(int x,int y,int k,int t){
 48     for(;x<=n;x+=x&-x) insert(rt[x],1,n,y,k,t);
 49 }
 50 int query_v(int p,int l,int r,int ql,int qr){
 51     if(!p) return 0;
 52     if(ql<=l&&qr>=r) return v[p];int mid=l+r>>1;
 53     int res=0;
 54     if(ql<=mid) res+=query_v(L[p],l,mid,ql,qr);
 55     if(qr>mid) res+=query_v(R[p],mid+1,r,ql,qr);
 56     return res;
 57 }
 58 int query_cnt(int p,int l,int r,int ql,int qr){
 59     if(!p) return 0;
 60     if(ql<=l&&qr>=r) return cnt[p];int mid=l+r>>1;
 61     int res=0;
 62     if(ql<=mid) res+=query_cnt(L[p],l,mid,ql,qr);
 63     if(qr>mid) res+=query_cnt(R[p],mid+1,r,ql,qr);
 64     return res;
 65 }
 66 ll Q_v(int l,int r,int ql,int qr){
 67     if(l>r||ql>qr) return 0;
 68     ll res=0;
 69     for(;r;r-=r&-r) res+=query_v(rt[r],1,n,ql,qr);
 70     for(--l;l;l-=l&-l) res-=query_v(rt[l],1,n,ql,qr);return res;
 71 }
 72 ll Q_cnt(int l,int r,int ql,int qr){
 73     if(l>r||ql>qr) return 0;
 74     ll res=0;
 75     for(;r;r-=r&-r) res+=query_cnt(rt[r],1,n,ql,qr);
 76     for(--l;l;l-=l&-l) res-=query_cnt(rt[l],1,n,ql,qr);return res;
 77 }
 78 inline void dec(ll &x,ll y){
 79     while(x<y) x+=mod;x-=y;
 80 }
 81 int main(){
 82     //freopen("testdata.in","r",stdin);
 83     n=read(),m=read();
 84     for(int i=1;i<=n;++i) a[i]=read(),b[i]=read();
 85     for(int i=n;i;--i) add(a[i],b[i]),(ans+=sum_v(a[i]-1)+sum_cnt(a[i]-1)*b[i])%=mod;
 86     for(int i=1;i<=n;++i) add(i,a[i],b[i],1);
 87     while(m--){
 88         int l=read(),r=read();
 89         if(l>r) swap(l,r);
 90         if(l==r) {print(ans);continue;}
 91         (ans+=Q_v(l+1,r-1,1,a[r]-1))%=mod;
 92         (ans+=Q_cnt(l+1,r-1,1,a[r]-1)*b[r])%=mod;
 93         dec(ans,Q_v(l+1,r-1,a[r]+1,n));
 94         dec(ans,Q_cnt(l+1,r-1,a[r]+1,n)*b[r]);
 95         (ans+=Q_v(l+1,r-1,a[l]+1,n))%=mod;
 96         (ans+=Q_cnt(l+1,r-1,a[l]+1,n)*b[l])%=mod;
 97         dec(ans,Q_v(l+1,r-1,1,a[l]-1));
 98         dec(ans,Q_cnt(l+1,r-1,1,a[l]-1)*b[l]);
 99         if(a[l]>a[r]) dec(ans,b[l]+b[r]);
100         else (ans+=b[l]+b[r])%=mod;
101         add(l,a[l],-b[l],-1),add(l,a[r],b[r],1);
102         add(r,a[r],-b[r],-1),add(r,a[l],b[l],1);
103         swap(a[l],a[r]),swap(b[l],b[r]);
104         print(ans);
105     }
106     Ot();
107     return 0;
108 }

 

posted @ 2018-09-01 14:14  bztMinamoto  阅读(242)  评论(0编辑  收藏  举报
Live2D