[bzoj3744]Gty的妹子序列

题目大意

在线兹瓷区间求逆序对个数。

双倍经验

最简单的做法是预处理ans和sum这个不用说了具体可以看根号算法题库里的经典分块思路。
当然这道题有升级版Gty的文艺妹子序列,那道题多一个修改操作。
反正我直接改了一下那题的代码交了。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<ctime>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int maxn=50000+10,maxc=250+10;
int ans[maxc][maxc],num[maxc];
int sum[maxc][maxn],tree[maxn];
int belong[maxn],a[maxn],b[maxn],sta[maxn];
int i,j,k,l,r,s,t,n,m,now,top,c;
bool czy;
int lowbit(int x){
    return x&-x;
}
void change(int k,int t){
    while(k<=n){  
        tree[k]+=t;  
        k+=lowbit(k);  
    }  
}
int query(int k){
    int t=0;  
    while (k){  
        t+=tree[k];  
        k-=lowbit(k);  
    }  
    return t;  
}
void change2(int id,int k,int t){
    while(k<=belong[n]){  
        ans[id][k]+=t;  
        k+=lowbit(k);  
    }  
}
int query2(int id,int k){
    int t=0;  
    while (k){  
        t+=ans[id][k];  
        k-=lowbit(k);  
    }  
    return t;  
}
void change3(int id,int k,int t){
    while(k<=n){  
        sum[id][k]+=t;  
        k+=lowbit(k);  
    }  
}
int query3(int id,int k){
    int t=0;  
    while (k){  
        t+=sum[id][k];  
        k-=lowbit(k);  
    }  
    return t;  
}
int read(){
    int x=0;
    char ch=getchar();
    while (ch<'0'||ch>'9') ch=getchar();
    while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x;
}
void write(int x){
    while (x){
        sta[++top]=x%10;
        x/=10;
    }
    while (top){
        putchar(sta[top]+'0');
        top--;
    }
    putchar('\n');
}
int main(){
    //freopen("data6.in","r",stdin);freopen("3787.out","w",stdout);
    czy=1;
    n=read();
    c=floor(sqrt(n));
    fo(i,1,n) a[i]=read(),b[i]=a[i],belong[i]=(i-1)/c+1;
    sort(b+1,b+n+1);
    l=unique(b+1,b+n+1)-b-1;
    fo(i,1,n) a[i]=lower_bound(b+1,b+l+1,a[i])-b;
    fo(i,1,belong[n]-1){
        fo(j,(i-1)*c+1,i*c) change(a[j],1);
        fo(j,i+1,belong[n]){
            t=0;
            fo(k,(j-1)*c+1,min(j*c,n)) t+=query(n)-query(a[k]);
            change2(i,j,t);
        }
        fo(j,(i-1)*c+1,i*c) change(a[j],-1);
    }
    fo(i,1,belong[n])
        fo(j,1,min(i*c,n)) change3(i,a[j],1);
    fo(i,1,belong[n]){
        fo(j,(i-1)*c+1,min(n,i*c)){
            num[i]+=query(n)-query(a[j]);
            change(a[j],1);
        }
        fo(j,(i-1)*c+1,min(n,i*c)) change(a[j],-1);
    }
    m=read();
    while (m--){
        j=read();k=read();
        if (czy) j^=now,k^=now;
        now=0;
        l=belong[j];r=belong[k];
        if (r-l<=1){
            fo(i,j,k){
                now+=query(n)-query(a[i]);
                change(a[i],1);
            }
            fo(i,j,k) change(a[i],-1);
                //write(now);
            printf("%d\n",now);
            continue;
        }
        fo(i,l+1,r-1){
            now+=num[i];
            now+=query2(i,r-1)-query2(i,i);
        }
        fo(i,j,l*c){
            now+=query(n)-query(a[i]);
            now+=query3(r-1,a[i]-1)-query3(l,a[i]-1);
            change(a[i],1);
        }
        fo(i,(r-1)*c+1,k){
            now+=query(n)-query(a[i]);
            now+=query3(r-1,n)-query3(r-1,a[i])-query3(l,n)+query3(l,a[i]);
            change(a[i],1);
        }
        fo(i,j,l*c) change(a[i],-1);
        fo(i,(r-1)*c+1,k) change(a[i],-1);
        //write(now);
        printf("%d\n",now);
    }
    //printf("\n%d\n",clock());
}

你可能感兴趣的:([bzoj3744]Gty的妹子序列)