luogu3759 不勤劳的图书管理员 (树状数组套线段树)
交换的话,只有它们中间的书会对答案产生影响
树状数组记位置,套线段树记书的编号 它对应的页数和书的个数
然后就是减掉中间那些原来是逆序对的,再把交换以后是逆序对的加上
别忘了考虑这两个自己交换以后是不是逆序的
最重要的一步:开个O2
1 #include<bits/stdc++.h> 2 #define CLR(a,x) memset(a,x,sizeof(a)) 3 using namespace std; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 typedef pair<ll,ll> pa; 7 const int maxn=5e4+10,lg2n=2e7+5,P=1e9+7; 8 9 inline ll rd(){ 10 ll x=0;char c=getchar();int neg=1; 11 while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();} 12 while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); 13 return x*neg; 14 } 15 16 17 namespace SegT{ 18 int ch[lg2n][2],pct; 19 ll sum[lg2n],cnt[lg2n]; 20 21 inline void update(int x){sum[x]=sum[ch[x][0]]+sum[ch[x][1]],cnt[x]=cnt[ch[x][0]]+cnt[ch[x][1]];} 22 23 inline void add(int &p,int l,int r,int x,int v){ 24 if(!p) p=++pct; 25 if(l==r) sum[p]+=v,cnt[p]+=(v>0?1:-1); 26 else{ 27 int m=l+r>>1; 28 if(x<=m) add(ch[p][0],l,m,x,v); 29 else add(ch[p][1],m+1,r,x,v); 30 update(p); 31 } 32 } 33 34 inline pa query(int p,int l,int r,int x,int y){ 35 if(!p) return make_pair(0,0); 36 if(x<=l&&r<=y) return make_pair(sum[p],cnt[p]); 37 else{ 38 int m=l+r>>1;pa r1=make_pair(0,0),r2=make_pair(0,0); 39 if(x<=m) r1=query(ch[p][0],l,m,x,y); 40 if(y>=m+1) r2=query(ch[p][1],m+1,r,x,y); 41 return make_pair(r1.first+r2.first,r1.second+r2.second); 42 } 43 } 44 } 45 46 int N,M,rt[maxn]; 47 int pg[maxn],a[maxn]; 48 49 inline int lowbit(int x){return x&(-x);} 50 51 inline void add(int x,int y,int v){ 52 for(;x<=N;x+=lowbit(x)) SegT::add(rt[x],1,N,y,v); 53 } 54 inline pa query(int xl,int xr,int yl,int yr){ 55 pa re=make_pair(0,0); 56 for(;xr;xr-=lowbit(xr)){ 57 pa x=SegT::query(rt[xr],1,N,yl,yr); 58 re.first+=x.first,re.second+=x.second; 59 } 60 for(xl--;xl;xl-=lowbit(xl)){ 61 pa x=SegT::query(rt[xl],1,N,yl,yr); 62 re.first-=x.first,re.second-=x.second; 63 } 64 return re; 65 } 66 67 68 int main(){ 69 //freopen("","r",stdin); 70 int i,j,k; 71 N=rd(),M=rd(); 72 for(i=1;i<=N;i++) a[i]=rd(),pg[i]=rd(); 73 ll ans=0; 74 for(i=1;i<=N;i++){ 75 pa re=query(1,i-1,a[i]+1,N); 76 ans+=re.first+re.second*pg[i],ans%=P; 77 add(i,a[i],pg[i]); 78 } 79 // printf("%d\n",ans); 80 for(i=1;i<=M;i++){ 81 int x=rd(),y=rd(); 82 if(x>y) swap(x,y); 83 pa re=query(x+1,y-1,1,a[x]-1); 84 ans-=re.first+re.second*pg[x],ans%=P; 85 86 re=query(x+1,y-1,a[y]+1,N); 87 ans-=re.first+re.second*pg[y],ans%=P; 88 if(a[x]>a[y]) ans-=pg[x]+pg[y],ans%=P; 89 90 re=query(x+1,y-1,1,a[y]-1); 91 ans+=re.first+re.second*pg[y],ans%=P; 92 93 re=query(x+1,y-1,a[x]+1,N); 94 ans+=re.first+re.second*pg[x],ans%=P; 95 if(a[x]<a[y]) ans+=pg[x]+pg[y]; 96 97 add(x,a[x],-pg[x]);add(x,a[y],pg[y]); 98 add(y,a[y],-pg[y]);add(y,a[x],pg[x]); 99 swap(a[x],a[y]);swap(pg[x],pg[y]); 100 printf("%lld\n",(ans+P)%P); 101 102 } 103 return 0; 104 }