解题思路
和以前做过的一道题有点像,就是区间逆序对之类的问题,用的是(BIT)套权值线段树,交换时讨论一下计算答案。。跑的不如暴力快。。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=50005;
const int M=N*200;
const int MOD=1e9+7;
typedef long long LL;
inline int rd(){
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
}
int n,m,a[N],val[N],tot,rt[N];
LL ans;
struct Segment_Tree{
int sum[M],num[M],ls[M],rs[M];
void update_num(int &x,int l,int r,int pos,int k){
if(!x) x=++tot; num[x]+=k; num[x]%=MOD;
if(l==r) return; int mid=(l+r)>>1;
if(pos<=mid) update_num(ls[x],l,mid,pos,k);
else update_num(rs[x],mid+1,r,pos,k);
}
void update_sum(int &x,int l,int r,int pos,int k){
if(!x) x=++tot; (sum[x]+=k)%=MOD;
if(l==r) return; int mid=(l+r)>>1;
if(pos<=mid) update_sum(ls[x],l,mid,pos,k);
else update_sum(rs[x],mid+1,r,pos,k);
}
int query_sum(int x,int l,int r,int L,int R){
if(!x) return 0; if(L<=l && r<=R) return sum[x];
int mid=(l+r)>>1,ret=0;
if(L<=mid) ret+=query_sum(ls[x],l,mid,L,R);
if(mid<R) (ret+=query_sum(rs[x],mid+1,r,L,R))%=MOD;
return ret;
}
int query_num(int x,int l,int r,int L,int R){
if(!x) return 0; if(L<=l && r<=R) return num[x];
int mid=(l+r)>>1,ret=0;
if(L<=mid) ret+=query_num(ls[x],l,mid,L,R);
if(mid<R) (ret+=query_num(rs[x],mid+1,r,L,R))%=MOD;
return ret;
}
}tree2;
struct BIT{
inline void add(int x,int k){
for(int i=x;i<=n;i+=i&-i) {
tree2.update_num(rt[i],1,50000,a[x],k);
tree2.update_sum(rt[i],1,50000,a[x],k*val[x]);
}
}
inline int query_sum(int l,int r,int L,int R){
if(l>r || L>R) return 0; int ret=0;
for(int i=r;i;i-=i&-i) (ret+=tree2.query_sum(rt[i],1,50000,L,R))%=MOD;
for(int i=l-1;i;i-=i&-i) (ret-=tree2.query_sum(rt[i],1,50000,L,R))%=MOD;
return (ret+MOD)%MOD;
}
inline int query_num(int l,int r,int L,int R){
if(l>r || L>R) return 0; int ret=0;
for(int i=r;i;i-=i&-i) (ret+=tree2.query_num(rt[i],1,50000,L,R))%=MOD;
for(int i=l-1;i;i-=i&-i) (ret-=tree2.query_num(rt[i],1,50000,L,R))%=MOD;
return (ret+MOD)%MOD;
}
}tree1;
int main(){
n=rd(),m=rd(); int x,y,tmp,num,num1,num2;
for(int i=1;i<=n;i++){
a[i]=rd(),val[i]=rd(); tree1.add(i,1);
ans+=tree1.query_sum(1,i,a[i]+1,50000);
ans+=1ll*tree1.query_num(1,i,a[i]+1,50000)*val[i]%MOD;
ans%=MOD;
} LL sum;
while(m--){
x=rd(),y=rd(); if(x>y) swap(x,y);
if(x==y) {printf("%lld
",ans); continue;}
if(a[x]<a[y]) (ans+=val[x]+val[y])%=MOD;
else (ans-=val[x]+val[y])%=MOD;
tmp=tree1.query_sum(x+1,y-1,min(a[x],a[y]),max(a[x],a[y]));
num=tree1.query_num(x+1,y-1,min(a[x],a[y]),max(a[x],a[y]));
num1=tree1.query_num(x+1,y-1,1,min(a[x],a[y])-1);
num2=tree1.query_num(x+1,y-1,max(a[x],a[y])+1,50000);
if(a[x]<a[y]) ans+=tmp*2%MOD+1ll*num*(val[x]+val[y])%MOD,ans%=MOD;
else ans-=tmp*2%MOD+1ll*num*(val[x]+val[y])%MOD,ans%=MOD;
sum=1ll*(val[y]-val[x])*num1%MOD+1ll*(val[x]-val[y])*num2%MOD; sum%=MOD;
(ans+=sum)%=MOD;
tree1.add(x,-1); tree1.add(y,-1); swap(a[x],a[y]); swap(val[x],val[y]);
tree1.add(x,1); tree1.add(y,1); ans=(ans+MOD)%MOD; printf("%lld
",ans);
}
return 0;
}