1. 程式人生 > >luogu3759 不勤勞的圖書管理員 (樹狀陣列套線段樹)

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 }