bzoj3289: Mato的文件管理
莫队算法+树状数组+离散化。
一定要注意莫队转移时增加或减少的逆序对数,比较容易写挂。
离散化那部分虽然效率很低,但是很好写,正确性也很容易保证,虽然会拖慢程序运行速度,但编码的复杂度却大大降低了。
我觉得是一种不错的选择。//反正是抄的黄学长的。。
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int maxn = 50000 + 10; int pos[maxn],a[maxn],n,m,block,l,r,ans,res[maxn]; int disc[maxn]; struct data { int l,r,id; }q[maxn]; bool cmp(data a,data b) { if(pos[a.l]==pos[b.l]) return a.r<b.r; return a.l<b.l; } struct BIT { int a[maxn]; inline int lowbit(int x) { return x&-x; } void add(int x,int val) { for(int i=x;i<=n;i+=lowbit(i)) a[i]+=val; } int query(int x) { int res=0; for(int i=x;i;i-=lowbit(i)) res+=a[i]; return res; } }bit; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); disc[i]=a[i]; } sort(disc+1,disc+n+1); for(int i=1;i<=n;i++) a[i]=lower_bound(disc+1,disc+n+1,a[i])-disc; scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } block = (int) sqrt(n+0.5); for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1; sort(q+1,q+m+1,cmp); l=1,r=0,ans=0; for(int i=1;i<=m;i++) { while(r<q[i].r) { r++; bit.add(a[r],1); ans+=r-l+1-bit.query(a[r]); } while(l<q[i].l) { bit.add(a[l],-1); ans-=bit.query(a[l]); l++; } while(l>q[i].l) { l--; ans+=bit.query(a[l]); bit.add(a[l],1); } while(r>q[i].r) { bit.add(a[r],-1); ans-=r-l-bit.query(a[r]); r--; } res[q[i].id]=ans; } for(int i=1;i<=m;i++) printf("%d\n",res[i]); return 0; }