[BZOJ 3289] Mato的文件管理 · 莫队算法 & 树状数组

来源:互联网 发布:罗技游戏鼠标mac设置 编辑:程序博客网 时间:2024/05/16 13:02

求不带修改的区间逆序对。

莫队直接上,用树状数组维护当前逆序对,每次转移是,所以总复杂度为.

#include <stdio.h>#include <algorithm>#include <string.h>#include <cmath>using namespace std;#define lowbit(x) ((x)&(-x)) const int N=50005;int n,m,a[N],b[N];int block,belong[N];int l,r;int Ans,ans[N];int t[N]; struct arr{    int l,r,num;}q[N]; bool cmp(const arr A,const arr B){    if (belong[A.l]==belong[B.l]) return A.r<B.r;    return A.l<B.l;} int get(){    int p=0;char x=getchar();    while (x<'0' || x>'9') x=getchar();    while (x>='0' && x<='9') p=p*10+x-'0',x=getchar();    return p;} int sum(int x){    int ret=0;    for (;x;x-=lowbit(x)) ret+=t[x];    return ret;} int add(int x,int k){    for (;x<=n;x+=lowbit(x)) t[x]+=k;} void init(){    n=get();    for (int i=1;i<=n;i++) a[i]=get(),b[i]=a[i];    sort(b+1,b+n+1);    int nn=unique(b+1,b+n+1)-b-1;    for (int i=1;i<=n;i++)        a[i]=lower_bound(b+1,b+nn+1,a[i])-b;         m=get();block=sqrt(n);    for (int i=1;i<=m;i++)        q[i].l=get(),q[i].r=get(),q[i].num=i,belong[i]=(i-1)/block+1;    sort(q+1,q+m+1,cmp);} int main(){    init();         l=1;r=0;Ans=0;    for (int i=1;i<=m;i++){        if (q[i].l==q[i].r){            ans[q[i].num]=0;            continue;        }        for (;l<q[i].l;l++) add(a[l],-1),Ans-=sum(a[l]-1);        for (;l>q[i].l;l--) add(a[l-1],1),Ans+=sum(a[l-1]-1);        for (;r<q[i].r;r++) add(a[r+1],1),Ans+=sum(n)-sum(a[r+1]);        for (;r>q[i].r;r--) add(a[r],-1),Ans-=sum(n)-sum(a[r]);        ans[q[i].num]=Ans;    }         for (int i=1;i<=m;i++)        printf("%d\n",ans[i]);    return 0;}


0 0