BZOJ3289: Mato的文件管理
$n \leq 50000$,$q \leq 50000$,$n$的数列$q$个询问,每次问某个区间只交换相邻俩数,要交换几次才能升序。数字范围不知反正要离散化。
注意不要学了莫队就把离线题套路忘了,询问右端点排序也是常用快捷方法。
好那我们试试。不会。好上莫队。
每次增加一个数,答案加上比他大(在右边加入)或比他小(在左边加入)的数。上树状数组。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 //#include<queue> 6 //#include<time.h> 7 //#include<complex> 8 #include<algorithm> 9 #include<stdlib.h> 10 using namespace std; 11 12 int n,m,tot,lq; 13 #define maxn 50011 14 int a[maxn],bel[maxn]; 15 struct Ques{int l,r,id;}q[maxn]; 16 bool cmp(const Ques a,const Ques b) {return bel[a.l]==bel[b.l]?a.r<b.r:a.l<b.l;} 17 18 int lisa[maxn],li,ans[maxn],ss; 19 struct BIT 20 { 21 int a[maxn],n; 22 void clear(int m) {n=m;} 23 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;} 24 int query(int x) {int ans=0; for (;x;x-=x&-x) ans+=a[x]; return ans;} 25 }t; 26 void modifyl(int x,int type) {ss+=type*t.query(a[x]-1); t.add(a[x],type);} 27 void modifyr(int x,int type) {ss+=type*(t.query(t.n)-t.query(a[x])); t.add(a[x],type);} 28 29 int main() 30 { 31 scanf("%d",&n); m=233; 32 for (int i=1;i<=n;i++) bel[i]=(i-1)/m+1; tot=bel[n]; 33 for (int i=1;i<=n;i++) scanf("%d",&a[i]),lisa[++li]=a[i]; 34 sort(lisa+1,lisa+1+li); li=unique(lisa+1,lisa+1+li)-lisa-1; 35 for (int i=1;i<=n;i++) a[i]=lower_bound(lisa+1,lisa+1+li,a[i])-lisa; 36 t.clear(li); 37 38 scanf("%d",&lq); 39 for (int i=1;i<=lq;i++) scanf("%d%d",&q[i].l,&q[q[i].id=i].r); 40 sort(q+1,q+1+lq,cmp); 41 int L=1,R=0; ss=0; 42 for (int i=1;i<=lq;i++) 43 { 44 while (L<q[i].l) modifyl(L,-1),L++; 45 while (L>q[i].l) L--,modifyl(L,1); 46 while (R<q[i].r) R++,modifyr(R,1); 47 while (R>q[i].r) modifyr(R,-1),R--; 48 ans[q[i].id]=ss; 49 } 50 for (int i=1;i<=lq;i++) printf("%d\n",ans[i]); 51 return 0; 52 }