[BJWC2017]神秘物质 Treap

非旋转Treap
合并相当于删除两个点增加一个点
查询直接把子树切出来再拼回去

#include <bits/stdc++.h>
#pragma GCC optimize(2)
#define L tr[t].l
#define R tr[t].r

#define N 200050
#define INF 2147483647
using namespace std;
typedef pair<int,int> pii;

#define MP make_pair
void GP(int &x,int &y,pii p) { x = p.first, y = p.second; }

struct Node{ int a,q,l,r,s1,s2,v1,v2,ans; }tr[N];
int sz[N],re,cnt,x,y,e,r1,r2,rt,n,m;

inline void ut(int &x,int y) {x = min(x,y);}
inline int Abs(int x) { return x<0 ? -x : x; }
inline int rd() { int r; scanf("%d",&r); return r; }
void up(int t) {
    assert(t);
    sz[t] = sz[L]+sz[R]+1;
    tr[t].s1 = min(tr[L].s1, tr[R].s1),
    tr[t].s1 = min(tr[t].s1, tr[t].a);
    tr[t].s2 = max(tr[L].s2, tr[R].s2);
    tr[t].s2 = max(tr[t].s2, tr[t].a);

    tr[t].ans = INF; 
    ut(tr[t].ans, tr[L].ans);
    ut(tr[t].ans, tr[R].ans);
    L ? ut(tr[t].ans, Abs(tr[t].a-tr[L].v2)) : (void)0;
    R ? ut(tr[t].ans, Abs(tr[t].a-tr[R].v1)) : (void)0;

    tr[t].v1 = L ? tr[L].v1 : tr[t].a,
    tr[t].v2 = R ? tr[R].v2 : tr[t].a;
}

int mer(int x,int y) {
    if (!x||!y) return x+y;
    return 
        tr[x].q < tr[y].q ?
        ( tr[x].r = mer(tr[x].r,y), up(x), x ):
        ( tr[y].l = mer(x,tr[y].l), up(y), y );
}

#define cr (sz[L]+1)
pii spl(int t,int k) {
    if (!k) return MP(0,t);
    if (k==sz[t]) return MP(t,0);
    return 
        k < cr ?
        ( GP(re, L, spl(L,k   )), up(t), MP(re,t) ):
        ( GP(R, re, spl(R,k-cr)), up(t), MP(t,re) );
}

int merge(int a,int b,int c) { return mer( mer(a,b),c ); }

void nN(int e) { 
    tr[++cnt] = (Node){e,rand(),0,0,e,e,e,e,INF}; sz[cnt] = 1; 
}

void solve1() {
    x = rd(), e = rd();
    GP(r1,rt,spl(rt,x-1)), GP(rt,r2,spl(rt,2));
    nN(e);
    rt = merge(r1,cnt,r2);
}

void solve2() {
    x = rd(), e = rd();
    GP(r1,r2,spl(rt,x));
    nN(e);
    rt = merge(r1,cnt,r2);
}

void solve3(int cd) {
    x = rd(), y = rd();
    GP(rt,r2,spl(rt,y)),
    GP(r1,rt,spl(rt,x-1));
    printf("%d\n",cd == 1 ? tr[rt].s2-tr[rt].s1 : tr[rt].ans);
    rt = merge(r1,rt,r2);
}

int main() {
    n = rd(), m = rd();
    tr[0].ans = INF, tr[0].s1 = INF, tr[0].s2 = -INF;
    for (int _=1;_<=n;_++) 
        nN(rd()), rt = _==1? 1 : mer(rt,_);
    while (m--) {
        char cmd[10]; scanf("%s",cmd+1);
        assert(1);
        cmd[1]+cmd[2] == 'm'+'e' ? solve1() :(void)0;
        cmd[1]+cmd[2] == 'i'+'n' ? solve2() :(void)0;
        cmd[1]+cmd[2] == 'm'+'a' ? solve3(1) :(void)0;
        cmd[1]+cmd[2] == 'm'+'i' ? solve3(2) :(void)0;
    }
    return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值