2141: 排队 分块+树状数组

分块,每个块内套一个树状数组。
qwq开始数组开小了RE。。。
整块的树状数组维护,块外的暴力统计就好了。
看到hzwer写了个一维的很厉害的样子qwq没仔细看150+行啊。。
膜ws_yzy树套树随便虐此题qwq,虽然跑了我两倍的时间qwq。。。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define lowbit(i) (i&(-i))
using namespace std;
int n,m,cnt,block,block_sum,ans;
int h[20005],num[20005],hash[20005],belong[20005],tree[200][20005];
inline int read()
{
    int a=0,f=1; char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
    while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
    return a*f;
}
inline int find(int x)
{
    int l=1,r=cnt;
    while (l<=r)
    {
        int mid=l+r>>1;
        if (hash[mid]==x) return mid;
        else if (hash[mid]<x) l=mid+1;
        else r=mid-1;
    }
}
inline void add(int block_id,int x,int val)
{
    for (int i=x;i<=cnt;i+=lowbit(i)) tree[block_id][i]+=val;
}
inline int query(int block_id,int x)
{
    int tmp=0;
    for (int i=x;i;i-=lowbit(i)) tmp+=tree[block_id][i];
    return tmp;
}
inline int work(int j,int ls,int rs)
{
    int x=find(h[j]);
    int tmp=0;
    if (x<ls) tmp-=1;
    if (x>ls) tmp+=1;
    if (x<rs) tmp+=1;
    if (x>rs) tmp-=1;
    return tmp;
}
int main()
{
    n=read();
    for (int i=1;i<=n;i++) h[i]=num[i]=read();
    sort(num+1,num+n+1);
    hash[++cnt]=num[1];
    for (int i=2;i<=n;i++)
        if (num[i]!=num[i-1]) hash[++cnt]=num[i];
    block=(int)(sqrt(n));
    if (n%block) block_sum=n/block+1; else block_sum=n/block;
    for (int i=1;i<=n;i++) belong[i]=(i-1)/block+1;
    for (int i=n;i;i--)
    {
        int x=find(h[i]);
        ans+=query(0,x-1);
        add(0,x,1);
    }
    for (int i=1;i<=block_sum;i++)
    {
        int l=(i-1)*block+1,r=min(n,i*block);
        for (int j=r;j>=l;j--)
        {
            int x=find(h[j]);
            add(i,x,1);
        }
    }
    printf("%d\n",ans);
    m=read();
    for (int i=1;i<=m;i++)
    {
        int l=read(),r=read();
        if (l>r) swap(l,r);
        int ls=find(h[l]),rs=find(h[r]);
        int x=belong[l],y=belong[r];
        if (x!=y)
        {
            for (int j=x+1;j<y;j++)
                ans+=query(j,rs-1)-query(j,cnt)+query(j,rs)-query(j,ls-1)+query(j,cnt)-query(j,ls);
            add(x,ls,-1); add(x,rs,1); add(y,rs,-1); add(y,ls,1);
            int l_r=x*block,r_l=(y-1)*block+1;
            for (int j=l+1;j<=l_r;j++) ans+=work(j,ls,rs);
            for (int j=r_l;j<r;j++) ans+=work(j,ls,rs);
        }
        else for (int j=l+1;j<r;j++) ans+=work(j,ls,rs);
        if (h[l]<h[r]) ans++; 
        else if (h[l]>h[r]) ans--;
        swap(h[l],h[r]);
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(2141: 排队 分块+树状数组)