【BZOJ3289】Mato的文件管理 莫队+树状数组

题目大意:给定一个长度为 N 的序列,M 个询问,每次询问区间逆序对的个数。

题解:用树状数组加速答案转移。

代码如下

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define cls(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int maxn=5e4+10;
const double eps=1e-6;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll fpow(ll a,ll b,ll c){ll ret=1%c;for(;b;b>>=1,a=a*a%c)if(b&1)ret=ret*a%c;return ret;}
inline ll read(){
    ll x=0,f=1;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    return f*x;
}
/*------------------------------------------------------------*/

int n,m,bsize,a[maxn],d[maxn],tot;
struct query{int id,bl,l,r;}q[maxn];
bool cmp(const query &x,const query &y){return x.bl!=y.bl?x.bl<y.bl:(x.bl&1)?x.r<y.r:x.r>y.r;}
inline int get(int x){return (x-1)/bsize+1;}

ll bit[maxn],now,l=1,r=0,ans[maxn];
void modify(int pos,ll val){
    for(int i=pos;i<=n;i+=i&-i)bit[i]+=val;
}
ll query(int pos){
    ll ret=0;
    for(int i=pos;i;i-=i&-i)ret+=bit[i];
    return ret;
}

void read_and_parse(){
    n=read(),bsize=sqrt(n);
    for(int i=1;i<=n;i++)a[i]=d[i]=read();
    sort(d+1,d+n+1);
    tot=unique(d+1,d+n+1)-d-1;
    for(int i=1;i<=n;i++)a[i]=lower_bound(d+1,d+tot+1,a[i])-d;
    m=read();
    for(int i=1;i<=m;i++){
        q[i].id=i,q[i].l=read(),q[i].r=read();
        q[i].bl=get(q[i].l);
    }
    sort(q+1,q+m+1,cmp);
}

inline void update(int pos,int f){
    if(f==0){// r +
        now+=query(n)-query(a[pos]);
        modify(a[pos],1);
    }
    else if(f==1){// r - 
        now-=query(n)-query(a[pos]);
        modify(a[pos],-1);
    }
    else if(f==2){// l - 
        now+=query(a[pos]-1);
        modify(a[pos],1);
    }
    else{
        now-=query(a[pos]-1);
        modify(a[pos],-1);
    }
}

void solve(){
    for(int i=1;i<=m;i++){
        while(r>q[i].r)update(r--,1);
        while(r<q[i].r)update(++r,0);
        while(l>q[i].l)update(--l,2);
        while(l<q[i].l)update(l++,3);
        ans[q[i].id]=now;
    }
    for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
}
int main(){
    read_and_parse();
    solve();
    return 0;
}
posted @ 2019-04-10 17:16  shellpicker  阅读(135)  评论(0编辑  收藏  举报