1. 程式人生 > >bzoj 2770 YY的Treap

bzoj 2770 YY的Treap

Written with StackEdit.

Description

志向遠大的\(YY\)小朋友在學完快速排序之後決定學習平衡樹,左思右想再加上\(SY\)的教唆,\(YY\)決定學習\(Treap\)。友愛教教父\(SY\)如砍瓜切菜般教會了\(YY\)小朋友\(Treap\)一種平衡樹,通過對每個節點隨機分配一個priority,同時保證這棵平衡樹關於priority是一個小根堆以保證效率)。這時候不怎麼友愛的\(510\)跑了出來,他問了\(YY\)小朋友一個極不和諧的問題:怎麼求\(Treap\)中兩個點之間的路徑長度。**\(YY\)秒了之後決定把這個問題交給你來做,但只要求出樹中兩點的\(LCA\)

Input

第一行兩個整數\(n,m.\)

第二行\(n\)個整數表示每個元素的\(key.\)

第三行\(n\)個整數表示每個元素的\(priority.\)

接下\(m\)行,每行一條命令,

\(I\) \(A\) \(B\),插入一個元素,\(key\)\(A,priority\)\(B.\)

\(D\) \(A\),刪除一個元素,\(key\)\(A\).

\(Q\) \(A\) \(B\),詢問\(key\)分別為\(A\)\(B\)\(LCA\)\(key.\)

Output

對於每個\(Q\)輸出一個整數。

Sample Input

2 2
1 2
4 5
Q 1 2
I 3 3

Sample Output

1

HINT

資料保證\(n<=10^5,m<=3*10^5\).

其餘整數均不超過\(int\)的範圍.

資料保證任意時刻樹中\(key\)\(priority\)均不相同.

Solution

  • 此題就是對\(treap\)基本性質的一個考察.
  • \(C\)\(A,B\)\(LCA\)(假設\(key_a<key_b\)).需要滿足\(key_c\in [key_a,key_b]\),這樣能保證\(A,B\)到根的路徑上都經過\(C\).
  • 而要求最近的公共祖先,根據\(priority\)滿足小根堆的性質,只需找出其中\(priority\)
    最小的點即為\(LCA\).
  • 可以建一顆權值線段樹,問題轉化為修改,刪除,以及區間上查詢最值.
#include<bits/stdc++.h> 
#define inf 0x7fffffff
#define root Tree[o]
#define lson Tree[o<<1]
#define rson Tree[o<<1|1]
using namespace std;
typedef long long LoveLive;
typedef pair<int,int> pii;
inline int read()
{
    int out=0,fh=1;
    char jp=getchar();
    while ((jp>'9'||jp<'0')&&jp!='-')
        jp=getchar();
    if (jp=='-')
        {
            fh=-1;
            jp=getchar();
        }
    while (jp>='0'&&jp<='9')
        {
            out=out*10+jp-'0';
            jp=getchar();
        }
    return out*fh;
}
const int MAXN=4e5+10;
int n,m;
struct Query{
    int op;
    int a,b;//key,pro
    int ans,id;
}q[MAXN];
int kc[MAXN];
struct node{
    int l,r,mi,pos,sum,val;
}Tree[MAXN<<3];
void phup(int o)
{
    if(lson.mi<rson.mi)
        root.mi=lson.mi,root.pos=lson.pos;
    else
        root.mi=rson.mi,root.pos=rson.pos;
    root.sum=lson.sum+rson.sum;
}
void bd(int l,int r,int o)
{
    int mid=(l+r)>>1;
    root.l=l,root.r=r;
    root.mi=inf;
    root.sum=0;
    if(l==r)
        return;
    bd(l,mid,o<<1);
    bd(mid+1,r,o<<1|1);
}
void add(int o,int x,int pos)
{
    int l=root.l,r=root.r;
    int mid=(l+r)>>1;
    if(l==r)
        {
            root.val=x;
            root.mi=x;
            root.pos=l;
            ++root.sum;
            return;
        }
    if(pos<=mid)
        add(o<<1,x,pos);
    else
        add(o<<1|1,x,pos);
    phup(o);
}
void del(int o,int pos)
{
    int l=root.l,r=root.r;
    int mid=(l+r)>>1;
    if(l==r)
        {
            root.mi=inf;
            --root.sum;
            return;
        }
    if(pos<=mid)
        del(o<<1,pos);
    else
        del(o<<1|1,pos);
    phup(o);
}
void ins(int x,int pos)
{
    add(1,x,pos);
}
void rem(int pos)
{
    del(1,pos);
}
int ansmi,anspos;
void qy(int o,int L,int R)
{
    int l=root.l,r=root.r;
    int mid=(l+r)>>1;
    if(r<L || l>R)
        return;
    if(L<=l && r<=R)
        {
            if(root.mi<ansmi)
                ansmi=root.mi,anspos=root.pos;
            return;
        }
    if(L<=mid)
        qy(o<<1,L,R);
    if(R>mid)
        qy(o<<1|1,L,R);
}
int main()
{
    n=read(),m=read();
    int cnt=0;
    for(int i=1;i<=n;++i)
        {
            q[i].op=1;
            q[i].a=read();
            kc[++cnt]=q[i].a;
            q[i].id=i;
        }
    for(int i=1;i<=n;++i)
        q[i].b=read();
    int idx=n;
    for(int i=1;i<=m;++i)
        {
            ++idx;
            q[idx].id=idx;
            char buf[2];
            scanf("%s",buf);
            if(buf[0]=='I')
                {
                    q[idx].op=1;
                    q[idx].a=read();
                    kc[++cnt]=q[idx].a;
                    q[idx].b=read();
                }
            else if(buf[0]=='D')
                {
                    q[idx].op=2;
                    q[idx].a=read();
                    kc[++cnt]=q[idx].a;
                }
            else
                {
                    q[idx].op=3;
                    q[idx].a=read();
                    kc[++cnt]=q[idx].a;
                    q[idx].b=read();
                    kc[++cnt]=q[idx].b;
                }
        }
    bd(1,2*n,1);
    sort(kc+1,kc+1+cnt);
    cnt=unique(kc+1,kc+1+cnt)-(kc+1);
    for(int i=1;i<=idx;++i)
        {
            if(q[i].op==1)
                {
                    q[i].a=lower_bound(kc+1,kc+1+cnt,q[i].a)-kc;
                    ins(q[i].b,q[i].a); 
                }
            else if(q[i].op==2)
                {
                    q[i].a=lower_bound(kc+1,kc+1+cnt,q[i].a)-kc;
                    rem(q[i].a);
                }
            else if(q[i].op==3)
                {
                     q[i].a=lower_bound(kc+1,kc+1+cnt,q[i].a)-kc;
                     q[i].b=lower_bound(kc+1,kc+1+cnt,q[i].b)-kc;
                     ansmi=inf;
                     qy(1,min(q[i].a,q[i].b),max(q[i].a,q[i].b));
                     printf("%d\n",kc[anspos]);
                }
        }
    return 0;
}