【loj2639】[Tjoi2017]不勤劳的图书管理员
#2639. 「TJOI2017」不勤劳的图书管理员
题目描述
输入格式
输出格式
样例
数据范围与提示
题意:每本书有次序和放的位置与权值,两本位置错乱的数会对答案贡献vi+vj , 每次交换两本书的位置,问每次操作之后的权值和;
题解:
将位置也看成次序的权值的话,其实就是维护动态的逆序对,只不过是两对的v都要贡献答案,维护的时候记录v的和 和 个数,交换l,r对[1,l-1]和[r+1,n]没有影响,对于l和r直接判断,l的变化值为减去[l+1,r-1]里面比v[l]小的再加上比v[l]大的,r同理,树状数组套主席树;
直接分块+树状数组的话会好写很多:https://www.cnblogs.com/CQzhangyu/p/7128300.html
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 #include<cmath> 7 #include<vector> 8 #include<stack> 9 #include<map> 10 #define Run(i,l,r) for(int i=l;i<=r;i++) 11 #define Don(i,l,r) for(int i=l;i>=r;i--) 12 #define ll long long 13 #define inf 0x3f3f3f3f 14 using namespace std; 15 const int N=50010,mod=1e9+7; 16 int n,m,p[N],w[N],ls[N*1000],rs[N*1000],rt[N],Rt[N],p1[N],p2[N],sz,cnt[N*1000],sum[N*1000]; 17 char gc(){ 18 static char*P1,*P2,s[1000000]; 19 if(P1==P2)P2=(P1=s)+fread(s,1,1000000,stdin); 20 return(P1==P2)?EOF:*P1++; 21 }// 22 int rd(){ 23 int x=0,f=1;char c=gc(); 24 while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();} 25 while(c>='0'&&c<='9'){x=x*10+c-'0',c=gc();} 26 return x*f; 27 }// 28 void ins(int&k,int last,int l,int r,int x,int v,int f){ 29 sum[k=++sz]=(sum[last]+v)%mod; 30 cnt[k]=cnt[last]+f; 31 ls[k]=ls[last],rs[k]=rs[last]; 32 if(l==r)return; 33 int mid=(l+r)>>1; 34 if(x<=mid)ins(ls[k],ls[last],l,mid,x,v,f); 35 else ins(rs[k],rs[last],mid+1,r,x,v,f); 36 }/// 37 int query(int k,int l,int r,int x,int y,int z){ 38 if(x>y)return 0; 39 if(l==x&&r==y)return (sum[k]+1ll*w[z]*cnt[k]%mod)%mod; 40 else{ 41 int mid=(l+r)>>1; 42 if(y<=mid)return query(ls[k],l,mid,x,y,z); 43 else if(x>mid)return query(rs[k],mid+1,r,x,y,z); 44 else return (query(ls[k],l,mid,x,mid,z) + query(rs[k],mid+1,r,mid+1,y,z))%mod; 45 } 46 }/// 47 int read(int x,int l,int r,int z){ 48 int ret = 0; 49 for(int i=x;i;i-=i&-i){ 50 ret = (ret + query(Rt[i],1,n,l,r,z)) %mod; 51 } 52 return ret; 53 }/// 54 void add(int x,int y,int v,int f){ 55 for(int i=x;i<=n;i+=i&-i){ 56 ins(Rt[i],Rt[i],1,n,y,v,f); 57 } 58 }/// 59 int Query(int k,int last,int l,int r,int x,int y,int z){ 60 if(x>y)return 0; 61 if(l==x&&r==y)return (sum[k]-sum[last]+1ll*w[z]*(cnt[k]-cnt[last])%mod)%mod; 62 else{ 63 int mid=(l+r)>>1; 64 if(y<=mid)return Query(ls[k],ls[last],l,mid,x,y,z); 65 else if(x>mid)return Query(rs[k],rs[last],mid+1,r,x,y,z); 66 else return (Query(ls[k],ls[last],l,mid,x,mid,z) + Query(rs[k],rs[last],mid+1,r,mid+1,y,z))%mod; 67 } 68 }/// 69 int main(){ 70 // freopen("loj1248.in","r",stdin); 71 // freopen("loj1248.out","w",stdout); 72 n=rd(),m=rd(); 73 Run(i,1,n)p[i]=rd(),w[i]=rd(); 74 ll ans = 0; 75 for(int i=1;i<=n;i++){ 76 ans=(ans+query(rt[i-1],1,n,p[i]+1,n,i))%mod; 77 ins(rt[i],rt[i-1],1,n,p[i],w[i],1); 78 } 79 for(int i=1,x,y;i<=m;i++){ 80 x=rd();y=rd(); 81 if(x>y)swap(x,y); 82 if(x==y){printf("%lld\n",ans);continue;} 83 if(p[x]>p[y])ans=(ans-w[x]-w[y])%mod;else ans=(ans+w[x]+w[y])%mod; 84 ans -= (ll)Query(rt[y-1],rt[x],1,n,1,p[x]-1,x) + read(y-1,1,p[x]-1,x) - read(x,1,p[x]-1,x);ans%=mod; 85 ans += (ll)Query(rt[y-1],rt[x],1,n,p[x]+1,n,x) + read(y-1,p[x]+1,n,x) - read(x,p[x]+1,n,x);ans%=mod; 86 ans -= (ll)Query(rt[y-1],rt[x],1,n,p[y]+1,n,y) + read(y-1,p[y]+1,n,y) - read(x,p[y]+1,n,y);ans%=mod; 87 ans += (ll)Query(rt[y-1],rt[x],1,n,1,p[y]-1,y) + read(y-1,1,p[y]-1,y) - read(x,1,p[y]-1,y);ans%=mod; 88 ans = (ans%mod+mod)%mod; 89 printf("%lld\n",ans); 90 add(x,p[x],-w[x],-1);add(y,p[y],-w[y],-1); 91 swap(p[x],p[y]);swap(w[x],w[y]); 92 add(x,p[x],w[x],1);add(y,p[y],w[y],1); 93 }// 94 return 0; 95 }//by tkys_Austin;