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 }
深深地明白自己的弱小