1. 程式人生 > >【[CQOI2011]動態逆序對】

【[CQOI2011]動態逆序對】

這是我的第一個資料結構套資料結構

不是線段樹套\(Splay\),而是非常蛇皮的塊狀連結串列套樹狀陣列

如果這裡按照\(\sqrt{n}\)的大小來分塊,那麼就需要\(n\sqrt{n}\)的空間,可能開不下,於是我們按照\(1000\)分塊,也就只會分出\(100\)個塊,就能開下空間了

之後每一次查詢的時候直接查詢樹狀陣列就好了,每次修改則非常的塊,直接找到對應的塊改動這個塊的樹狀陣列就好了

程式碼

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define lowbit(x) ((x)&(-x))
#define re register
#define maxn 100005
#define LL long long
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
int a[maxn],b[maxn];
int l[1005],r[1005],sz[1005];
inline int read()
{
    char c=getchar();
    int x=0;
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9')
        x=(x<<3)+(x<<1)+c-48,c=getchar();
    return x;
}
int c[maxn];
int bit[101][maxn];
int n,m,tot,len;
LL ans;
int to[maxn],vis[maxn];
inline void add(int x)
{
    for(re int i=x;i<=n;i+=lowbit(i))
        c[i]++;
}
inline int ask(int x)
{
    int now=0;
    for(re int i=x;i;i-=lowbit(i))
        now+=c[i];
    return now;
}
inline void get_pair()
{
    for(re int i=1;i<=n;i++)
    {
        ans+=ask(n)-ask(a[i]);
        add(a[i]);
    }
}
inline void B_add(int o,int x,int val)
{
    for(re int i=x;i<=n;i+=lowbit(i)) bit[o][i]+=val;
}
inline int B_ask(int o,int x)
{
    int now=0;
    for(re int i=x;i;i-=lowbit(i)) now+=bit[o][i];
    return now;
}
inline void build_block()
{
    len=1000;
    int k=1;
    while(k<=n)
    {
        l[++tot]=k;
        r[tot]=min(n,k+len-1);
        k=r[tot]+1;
        for(re int i=l[tot];i<=r[tot];i++) 
            B_add(tot,a[i],1);
    }
}
inline int get_num(int x)
{
    if(x%len==0) return x/len;
    return x/len+1;
}
inline void BL_change(int x)
{
    vis[to[x]]=1;
    int now=get_num(to[x]);
    B_add(now,x,-1);
}
inline int BL_find_less(int x,int y,int val)
{
    int num=0;
    for(re int i=x;i<=y;i++)
        if(!vis[i]&&a[i]<val) num++;
    return num;
}
inline int BL_find_more(int x,int y,int val)
{
    int num=0;
    for(re int i=x;i<=y;i++)
        if(!vis[i]&&a[i]>val) num++;
    return num;
}
inline int find_less(int x,int y,int val)
{
    int num=0;
    for(re int i=1;i<=tot;i++)
    {
        if(x>l[i]&&y<r[i]) return BL_find_less(x,y,val);
        if(x<=l[i]&&y>=r[i]) num+=B_ask(i,val);
            else if(x<=l[i]&&y<r[i]) num+=BL_find_less(l[i],y,val);
                else if(y>=r[i]&&x>l[i]) num+=BL_find_less(x,r[i],val);
    }
    return num;
}
inline int find_more(int x,int y,int val)
{
    int num=0;
    for(re int i=1;i<=tot;i++)
    {
        if(x>l[i]&&y<r[i]) return BL_find_more(x,y,val);
        if(x<=l[i]&&y>=r[i]) num+=B_ask(i,n)-B_ask(i,val);
            else if(x<=l[i]&&y<r[i]) num+=BL_find_more(l[i],y,val);
                else if(y>=r[i]&&x>l[i]) num+=BL_find_more(x,r[i],val);
    }
    return num;
}
int main()
{
    n=read(),m=read();
    for(re int i=1;i<=n;i++) a[i]=read(),to[a[i]]=i;
    get_pair(),build_block();
    int x;
    while(m--)
    {
        printf("%lld\n",ans);
        x=read();
        if(to[x]!=1) ans-=find_more(1,to[x]-1,x);
        if(to[x]!=n) ans-=find_less(to[x]+1,n,x);
        BL_change(x);
    }
    return 0;
}