【題解】Luogu P1533 可憐的狗狗

原題傳送門

莫隊介紹,Splay介紹

離線的題目,莫隊是不錯的解決方法

先把詢問排一下序

剩下就套一個莫隊的板子

每來一隻狗就把漂亮值插入平衡樹

每去掉一隻狗就把漂亮值從平衡樹中刪掉

每次查詢查平衡樹中第k小

#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define N 800005
#define M 50005
using namespace std;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf; 
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 
}
inline int read()
{
    register int x=0,f=1;register char ch=nc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=nc();
    return x*f;
}
inline void write(register int x)
{
    if(!x)putchar('0');if(x<0)x=-x,putchar('-');
    static int sta[20];register int tot=0;
    while(x)sta[tot++]=x%10,x/=10;
    while(tot)putchar(sta[--tot]+48);
}
struct Splay{
    int v,fa,ch[2],sum,rec;
}tree[N];
int tot=0;
inline void update(register int x)
{
    tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+tree[x].rec;
}
inline bool findd(register int x)
{
    return tree[tree[x].fa].ch[0]==x?0:1;
}
inline void connect(register int x,register int fa,register int son)
{
    tree[x].fa=fa;
    tree[fa].ch[son]=x;
} 
inline void rotate(register int x)
{
    int Y=tree[x].fa;
    int R=tree[Y].fa;
    int Yson=findd(x);
    int Rson=findd(Y);
    int B=tree[x].ch[Yson^1];
    connect(B,Y,Yson);
    connect(Y,x,Yson^1);
    connect(x,R,Rson);
    update(Y),update(x);
}
inline void splay(register int x,register int to)
{
    to=tree[to].fa;
    while(tree[x].fa!=to)
    {
        int y=tree[x].fa;
        if(tree[y].fa==to)
            rotate(x);
        else if(findd(x)==findd(y))
            rotate(y),rotate(x);
        else
            rotate(x),rotate(x);
    }   
}
inline int newpoint(register int v,register int fa)
{
    tree[++tot].fa=fa;
    tree[tot].v=v;
    tree[tot].sum=tree[tot].rec=1;
    return tot; 
}
inline void Insert(register int x)
{
    int now=tree[0].ch[1];
    if(tree[0].ch[1]==0)
    {
        newpoint(x,0);
        tree[0].ch[1]=tot;
    }
    else
    {
        while(19260817)
        {
            ++tree[now].sum;
            if(tree[now].v==x)
            {
                ++tree[now].rec;
                splay(now,tree[0].ch[1]);
                return;
            }
            int nxt=x<tree[now].v?0:1;
            if(!tree[now].ch[nxt])
            {
                int p=newpoint(x,now);
                tree[now].ch[nxt]=p;
                splay(p,tree[0].ch[1]);
                return;
            }
            now=tree[now].ch[nxt];
        }
    }
}
inline int find(register int v)
{
    int now=tree[0].ch[1];
    while(19260817)
    {
        if(tree[now].v==v)
        {
            splay(now,tree[0].ch[1]);
            return now;
        }
        int nxt=v<tree[now].v?0:1;
        if(!tree[now].ch[nxt])
            return 0;
        now=tree[now].ch[nxt];
    }
}
inline void delet(register int x)
{
    int pos=find(x);
    if(!pos)
        return;
    if(tree[pos].rec>1)
    {
        --tree[pos].rec;
        --tree[pos].sum;
    }
    else
    {
        if(!tree[pos].ch[0]&&!tree[pos].ch[1])
            tree[0].ch[1]=0;
        else if(!tree[pos].ch[0])
        {
            tree[0].ch[1]=tree[pos].ch[1];
            tree[tree[0].ch[1]].fa=0;
        }
        else
        {
            int left=tree[pos].ch[0];
            while(tree[left].ch[1])
                left=tree[left].ch[1];
            splay(left,tree[pos].ch[0]);
            connect(tree[pos].ch[1],left,1);
            connect(left,0,1);
            update(left);
        }
    }
}
inline int arank(register int x)
{
    int now=tree[0].ch[1];
    while(19260817)
    {
        int used=tree[now].sum-tree[tree[now].ch[1]].sum;
        if(x>tree[tree[now].ch[0]].sum&&x<=used)
        {
            splay(now,tree[0].ch[1]);
            return tree[now].v;
        }
        if(x<used)
            now=tree[now].ch[0];
        else
            x-=used,now=tree[now].ch[1];
    }
}
struct query{
    int l,r,id,bl,k;
}q[M];
int a[N],blocksize=0,ans[M];
inline bool cmp(register query a,register query b)
{
    return a.bl!=b.bl?a.l<b.l:((a.bl&1)?a.r<b.r:a.r>b.r);
}
int main()
{
    int n=read(),m=read();
    blocksize=sqrt(m);
    for(register int i=1;i<=n;++i)
        a[i]=read();
    for(register int i=1;i<=m;++i)
    {
        int l=read(),r=read(),k=read();
        q[i]=(query){l,r,i,l/blocksize,k};
    }
    sort(q+1,q+m+1,cmp);
    int l=1,r=0;
    for(register int i=1;i<=m;++i)
    {
        int ll=q[i].l,rr=q[i].r;
        while(ll<l)
            Insert(a[--l]);
        while(rr>r)
            Insert(a[++r]);
        while(ll>l)
            delet(a[l++]);
        while(rr<r)
            delet(a[r--]);
        ans[q[i].id]=arank(q[i].k);
    }
    for(register int i=1;i<=m;++i)
        write(ans[i]),puts("");
    return 0;
}
相關文章
相關標籤/搜索