首先允许离线,一眼莫队……
然后考虑对于每次移动,这不就是让你求逆序对嘛(QAQ)
考虑怎么移动?
- 每次在最后添加一个数,比这个数大的数都会与其形成一个逆序对
- 每次在最后移除一个数,比这个数大的数都会与其形成一个逆序对
- 每次在最前添加一个数,比这个数小的数都会与其减少一个逆序对
- 每次在最前移除一个数,比这个数小的数都会与其减少一个逆序对
那么每次移动的时候我拿树状数组查询一下就好,注意要离散化。
1 #include<bits/stdc++.h> 2 #define N 50005 3 #define inf 1000000007 4 using namespace std; 5 typedef unsigned int uint; 6 uint ans[N],now; 7 int n,m,a[N],b[N],rt[N]; 8 int c[20*N]; 9 struct Query{int l,r,id;}q[2*N]; 10 inline int lowbit(int x){return x&(-x);} 11 bool operator<(Query x,Query y){ 12 if(rt[x.l]==rt[y.l])return x.r<y.r; 13 return rt[x.l]<rt[y.l]; 14 } 15 inline void add(int x,int val){ 16 for(int i=x;i<=n;i+=lowbit(i))c[i]+=val; 17 } 18 uint ask(int x){ 19 uint ans=0; 20 for(int i=x;i;i-=lowbit(i))ans+=c[i]; 21 return ans; 22 } 23 inline int read(){ 24 int f=1,x=0;char ch; 25 do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9'); 26 do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9'); 27 return f*x; 28 } 29 int main(){ 30 n=read();int x=(int)sqrt(n); 31 for(int i=1;i<=n;i++)a[i]=read(),b[i]=a[i]; 32 sort(b+1,b+n+1); 33 for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+n+1,a[i])-b; 34 m=read(); 35 for(int i=1;i<=m;i++)q[i].l=read(),q[i].r=read(),q[i].id=i; 36 for(int i=1;i<=n;i++)rt[i]=(i-1)/x+1; 37 sort(q+1,q+m+1); 38 int l=1,r=0; 39 for(int i=1;i<=m;i++){ 40 while(l<q[i].l)add(a[l],-1),now-=ask(a[l]-1),l++; 41 while(r>q[i].r)add(a[r],-1),now-=r-l-ask(a[r]),r--; 42 while(l>q[i].l)l--,add(a[l],1),now+=ask(a[l]-1); 43 while(r<q[i].r)r++,add(a[r],1),now+=r-l+1-ask(a[r]); 44 ans[q[i].id]=now; 45 } 46 for(int i=1;i<=m;i++)printf("%d ",ans[i]); 47 return 0; 48 }