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 }

猜你喜欢

转载自www.cnblogs.com/Ressed/p/9997097.html