bzoj 2141: 排队
Posted ws_ccd
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 2141: 排队相关的知识,希望对你有一定的参考价值。
就是求个动态区间逆序对??是不是和GTY文艺妹子差不多??哦,不是,,,
这个题的话,可以发现的是,每次交换只会对区间内的数产生影响,所以就是求一下区间内比这个L(区间左端点)大的,小的,(减小,加大)比R(区间右端点)大的,小的,(减大,加小),然后把连个数换一下就就行了。。我记得是这样。。而且这个sb题也是调了好久、、、
1 #include<bits/stdc++.h> 2 #define N 100005 3 #define LL long long 4 #define inf 0x3f3f3f3f 5 using namespace std; 6 inline int ra() 7 { 8 int x=0,f=1; char ch=getchar(); 9 while (ch<‘0‘ || ch>‘9‘) {if (ch==‘-‘) f=-1; ch=getchar();} 10 while (ch>=‘0‘ && ch<=‘9‘) {x=x*10+ch-‘0‘; ch=getchar();} 11 return x*f; 12 } 13 const int M=5000005; 14 int a[N],sz,n,ans; 15 int ls[M],rs[M],s[M],w[M],v[M],rnd[M],root[M]; 16 void update(int k){s[k]=s[ls[k]]+s[rs[k]]+w[k];} 17 void rturn(int &k){int t=ls[k]; ls[k]=rs[t]; rs[t]=k; s[t]=s[k]; update(k); k=t;} 18 void lturn(int &k){int t=rs[k]; rs[k]=ls[t]; ls[t]=k; s[t]=s[k]; update(k); k=t;} 19 void insert(int &k, int num) 20 { 21 if (!k) { 22 k=++sz; w[k]=s[k]=1; ls[k]=rs[k]=0; v[k]=num; rnd[k]=rand(); return; 23 } 24 s[k]++; 25 if (num==v[k]) w[k]++; 26 else if (num<v[k]) {insert(ls[k],num); if (rnd[ls[k]]<rnd[k]) rturn(k); } 27 else {insert(rs[k],num); if (rnd[rs[k]]<rnd[k]) lturn(k);} 28 } 29 void del(int &k, int num) 30 { 31 if (v[k]==num) 32 { 33 if (w[k]>1) {s[k]--; w[k]--; return;} 34 if (ls[k]*rs[k]==0) k=ls[k]+rs[k]; 35 else {if (rnd[ls[k]]<rnd[rs[k]]) rturn(k), del(k,num); 36 else lturn(k),del(k,num); 37 } 38 } 39 else if (num<v[k]) del(ls[k],num),s[k]--; 40 else del(rs[k],num),s[k]--; 41 } 42 void build(int k, int l, int r, int x, int num) 43 { 44 insert(root[k],num); 45 if (l==r) return; 46 int mid=l+r>>1; 47 if (x<=mid) build(k<<1,l,mid,x,num); 48 else build(k<<1|1,mid+1,r,x,num); 49 } 50 int find1(int k, int num) 51 { 52 if (!k) return 0; 53 if (num==v[k]) return s[ls[k]]; 54 else if (num<v[k]) return find1(ls[k],num); 55 else return w[k]+s[ls[k]]+find1(rs[k],num); 56 } 57 int ask1(int k ,int l, int r, int x, int y, int num) 58 { 59 if (l>r || x>y) return 0; 60 if (l==x && y==r) return find1(root[k],num); 61 int mid=l+r>>1; 62 if (y<=mid) return ask1(k<<1,l,mid,x,y,num); 63 else if (x>mid) return ask1(k<<1|1,mid+1,r,x,y,num); 64 else return ask1(k<<1,l,mid,x,mid,num)+ask1(k<<1|1,mid+1,r,mid+1,y,num); 65 } 66 int find(int k, int num) 67 { 68 if (!k) return 0; 69 if (num==v[k]) return s[ls[k]]+w[k]; 70 else if (num<v[k]) return find(ls[k],num); 71 else return w[k]+s[ls[k]]+find(rs[k],num); 72 } 73 int ask(int k ,int l, int r, int x, int y, int num) 74 { 75 if (l>r || x>y) return 0; 76 if (l==x && y==r) return find(root[k],num); 77 int mid=l+r>>1; 78 if (y<=mid) return ask(k<<1,l,mid,x,y,num); 79 else if (x>mid) return ask(k<<1|1,mid+1,r,x,y,num); 80 else return ask(k<<1,l,mid,x,mid,num)+ask(k<<1|1,mid+1,r,mid+1,y,num); 81 } 82 void change(int k, int l, int r, int pos, int old, int num) 83 { 84 del(root[k],old); insert(root[k],num); 85 if (l==r) return; 86 int mid=l+r>>1; 87 if (pos<=mid) change(k<<1,l,mid,pos,old,num); 88 else change(k<<1|1,mid+1,r,pos,old,num); 89 } 90 int main() 91 { 92 n=ra(); 93 for (int i=1; i<=n; i++) 94 { 95 a[i]=ra(); 96 build(1,1,n,i,a[i]); 97 ans+=(i-1-ask(1,1,n,1,i-1,a[i])); 98 // cout<<(i-1-ask(1,1,n,1,i-1,a[i]))<<endl; 99 } 100 printf("%d\n",ans); 101 int m=ra(); 102 while (m--) 103 { 104 int x=ra(),y=ra(); 105 if (x>y) swap(x,y); 106 if (a[x]>a[y]) ans--; if (a[x]<a[y]) ans++; 107 ans+=ask(1,1,n,x+1,y-1,a[y])+ask1(1,1,n,x+1,y-1,a[y])-ask(1,1,n,x+1,y-1,a[x])-ask1(1,1,n,x+1,y-1,a[x]); 108 change(1,1,n,x,a[x],a[y]); change(1,1,n,y,a[y],a[x]); 109 swap(a[x],a[y]); 110 // for (int i=1; i<=n; i++) printf("%d ",a[i]); cout<<endl; 111 printf("%d\n",ans); 112 } 113 return 0; 114 }
以上是关于bzoj 2141: 排队的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ 2141 排队(块套树,分块,树状数组)BZOJ修复工程