LCT模板

【清华集训2016】温暖会指引我们前行 为例
UOJ 274

#include <cstdio>
#include <cstring>
#define R register
#define Null b
#define Min(_A, _B) (_A < _B ? _A : _B)
const int Inf = 2147483647;
struct Data{ int val, tmp, len, sum; bool rev; Data *Pre, *Son[2]; } b[400010];
bool check_root(R Data *Now){ return (Now->Pre->Son[0] != Now && Now->Pre->Son[1] != Now); }
template <class TT> void Swap(TT &A, TT &B){ R TT tt = A; A = B, B = tt; }
void Pushdown(R Data *Now){ if(Now->rev) Now->rev = 0, Swap(Now->Son[0], Now->Son[1]), Now->Son[0]->rev ^= 1, Now->Son[1]->rev ^= 1; }
void Pushup(R Data *Now)
{
    Now->sum = Now->Son[0]->sum + Now->Son[1]->sum + Now->len;
    Now->tmp = Min(Now->Son[0]->tmp, Min(Now->Son[1]->tmp, Now->val));
}
void Preview(R Data *Now){ if(!check_root(Now)) Preview(Now->Pre); Pushdown(Now); }
void Rotate(R Data *Now)
{
    R Data *f = Now->Pre;
    R int d = (f->Son[1] == Now);
    (f->Son[d] = Now->Son[!d])->Pre = f;
    Now->Pre = f->Pre;
    if(!check_root(f)) f->Pre->Son[f->Pre->Son[1] == f] = Now;
    (Now->Son[!d] = f)->Pre = Now;
    Pushup(f);
}
void Splay(R Data *Now)
{
    Preview(Now);
    while(!check_root(Now))
    {
        if(!check_root(Now->Pre)) Rotate((Now->Pre->Pre->Son[0] == Now->Pre) ^ (Now->Pre->Son[0] == Now) ? Now : Now->Pre); 
        Rotate(Now);
    }
    Pushup(Now);
}
void Query_min(R Data *A, R Data *&Tmp)
{
    if(A->val < Tmp->val) Tmp = A;
    if(A->val == A->tmp) return ;
    if(A->Son[0]->tmp < A-> Son[1]->tmp) Query_min(A->Son[0], Tmp);
    else Query_min(A->Son[1], Tmp);
}
void Access(R Data *A){ R Data *last = Null; while(A != Null){ Splay(A), A->Son[1] = last; Pushup(A), last = A, A = A->Pre; } }
void Make_Root(R Data *A){ Access(A); Splay(A); A->rev ^= 1; }
void Link(R Data *A, R Data *B){ Make_Root(A), A->Pre = B, Access(A); }
void Cut(R Data *A, R Data *B){ Make_Root(A), Access(B), Splay(B), A->Pre = B->Son[0] = Null; Pushup(B); }
Data *Find_Root(R Data *A)
{
    Access(A); Splay(A);
    while(A->Son[0] != Null) A = A->Son[0]; return A; 
}
int U[300010], V[300010];
bool vis[300010];
int main()
{
    b[0] = (Data){Inf, Inf, 0, 0, 0, Null, {Null, Null}};
    int n, m;
    scanf("%d %d", &n, &m);
    for(R int i = 1; i <= n; i++) b[i] = b[0];
    for(R int i = 1; i <= m; i++)
    {
        R char str[10];
        scanf("%s", str);
        if(str[0] == 'f')
        {
            R int Id, u, v, t, l;
            scanf("%d %d %d %d %d", &Id, &u, &v, &t, &l);
            u++, v++, Id++;
            R Data *A = Find_Root(b + u), *B = Find_Root(b + v);
            b[Id + n] = (Data){t, t, l, l, 0, Null, {Null, Null}};
            if(A == B)
            {
                Make_Root(b + u), Access(b + v); Splay(b + u), Query_min(b + u, A = b + u); // printf("%d ?\n", A - b);
                if(A->val >= t){ Splay(A); continue; }

                Cut(A, b + U[A - b - n]), Cut(A, b + V[A - b - n]); vis[A - b - n] = 0;
            }
            vis[Id] = 1; U[Id] = u, V[Id] = v;
            Link(b + u, b + Id + n), Link(b + Id + n, b + v);
        }
        else if(str[0] == 'm')
        {
            R int u, v;
            scanf("%d %d", &u, &v);
            u++, v++;
            R Data *A = Find_Root(b + u), *B = Find_Root(b + v);
            if(A != B){ puts("-1"); continue; }
            Make_Root(b + u), Access(b + v); Splay(b + v);
            printf("%d\n", b[v].sum);
        }
        else 
        {
            R int Id, l;
            scanf("%d %d", &Id, &l);
            Id++;
            if(vis[Id]) b[Id + n].len = l, Splay(b + Id + n);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值