bzoj2141: 排队

诶这这这这怎么又是树状数组和逆序对(快要被虐哭了55555)

强行分块。。。

我们先开block个权值树状数组,把每个块的值插进去,块里面的直接算,外面的靠树状数组

if sum ++ -- 好烦。。

然而对拍是个好东西。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int s[150][21000];
int lowbit(int x){return x&-x;}
void change(int x,int w,int k)
{
    while(x<=20100)
    {
        s[w][x]+=k;
        x+=lowbit(x);
    }
}
int getsum(int x,int w)
{
    int ret=0;
    while(x>0)
    {
        ret+=s[w][x];
        x-=lowbit(x);
    }
    return ret;
}

//----------bit------------------------

int a[21000];
int lslen,ls[21000];

int block,st[21000];
int main()
{
    freopen("data.in","r",stdin);
    freopen("1.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),ls[++lslen]=a[i];
    sort(ls+1,ls+lslen+1);
    lslen=unique(ls+1,ls+lslen+1)-ls-1;
    for(int i=1;i<=n;i++)
        a[i]=lower_bound(ls+1,ls+lslen+1,a[i])-ls;
    
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        sum+=(i-1-getsum(a[i],1));
        change(a[i],1,1);
    }
    memset(s[1],0,sizeof(s[1]));
    printf("%d\n",sum);
    
    //--------sc&&LSH&&初始逆序对数----------------- 
    
    block=int(sqrt(double(n+1)));
    for(int i=1;i<=n;i++)
    {
        st[i]=(i-1)/block+1;
        change(a[i],st[i],1);
    }
    
    int Q,x,y;
    scanf("%d",&Q);
    while(Q--)
    {
        scanf("%d%d",&x,&y);
        if(x>y)swap(x,y);
        if(a[x]>a[y])sum--;
        if(a[x]<a[y])sum++;
        
        if(st[x]==st[y])
        {
            for(int i=x+1;i<=y-1;i++)
            {
                if(a[x]>a[i])sum--;
                if(a[x]<a[i])sum++;
                if(a[y]>a[i])sum++;
                if(a[y]<a[i])sum--;
            }
            swap(a[x],a[y]);
        }
        else
        {
            for(int i=x+1;i<=st[x]*block;i++)
            {
                if(a[x]>a[i])sum--;
                if(a[x]<a[i])sum++;
                if(a[y]>a[i])sum++;
                if(a[y]<a[i])sum--;
            }
            for(int i=(st[y]-1)*block+1;i<=y-1;i++)
            {
                if(a[x]<a[i])sum++;
                if(a[x]>a[i])sum--;
                if(a[y]<a[i])sum--;
                if(a[y]>a[i])sum++;
            }
            for(int i=st[x]+1;i<=st[y]-1;i++)
            {
                sum-=getsum(a[x]-1,i);
                sum+=block-getsum(a[x],i);
                
                sum+=getsum(a[y]-1,i);
                sum-=block-getsum(a[y],i);
            }
            
            change(a[x],st[x],-1);
            change(a[y],st[y],-1);
            swap(a[x],a[y]);
            change(a[x],st[x],1);
            change(a[y],st[y],1);
        }
        printf("%d\n",sum);
    }
    return 0;
}

 

posted @ 2018-04-18 21:19  AKCqhzdy  阅读(101)  评论(0编辑  收藏  举报