bzoj 4817: [Sdoi2017]树点涂色

来源:互联网 发布:最好用黑客linux系统 编辑:程序博客网 时间:2024/05/20 10:56

lct。
第一个操作就是access的过程中,把当前点的prefer child子树(也就是要断掉的重链那边,所有的点答案加1),然后就是新的prefer child的子树里面所有节点答案减1,因为lct是splay维护的,所以就要沿着splay往左走,找到深度最小的节点,用dfs序更新
第二个操作就是查询x,y到根的答案,再减去2倍的lca,加上1(lca被减了2次
第三种操作就是查询子树的最大值。

#include <bits/stdc++.h>using namespace std;#define LL long long#define ULL unsigned long long#define pii pair<int, int>#define MP make_pair#define ls i << 1#define rs ls | 1#define md (ll + rr >> 1)#define lson ll, md, ls#define rson md + 1, rr, rs#define mod 1000000007#define inf 0x3f3f3f3f#define Pi acos(-1.0)#define eps 1e-12#define N 200020#define M 400020int fst[N], vv[M], nxt[M], e;int L[N], R[N], lab[N], dc;int dep[N], fa[N][22];int ch[N][2], pre[N];int n, m;int mx[N<<2], down[N<<2];void init(){    for(int i = 0; i <= n; ++i) fst[i] = -1; e = 0;}void add(int u, int v){    vv[e] = v, nxt[e] = fst[u], fst[u] = e++;}void update(int l, int r, int v, int ll, int rr, int i){//  printf("%d %d %d %d\n", l, r, ll, rr);    if(l == ll && r == rr){        down[i] += v;        mx[i] += v;        return ;    }    if(r <= md) update(l, r, v, lson);    else if(l > md) update(l, r, v, rson);    else update(l, md, v, lson), update(md + 1, r, v, rson);    mx[i] = max(mx[ls], mx[rs]) + down[i];}int query(int l, int r, int ll, int rr, int i){    if(l == ll && r == rr) return mx[i];    int ret = 0;    if(r <= md) ret = query(l, r, lson);    else if(l > md) ret = query(l, r, rson);    else ret = max(query(l, md, lson), query(md + 1, r, rson));    return ret + down[i];}void dfs(int u, int p, int d){    fa[u][0] = p, dep[u] = d;    L[u] = ++dc, lab[dc] = u;    pre[u] = p;     ch[u][0] = ch[u][1] = 0;    for(int i = fst[u]; ~i; i = nxt[i]){        int v = vv[i];        if(v == p) continue;        dfs(v, u, d + 1);    }    update(L[u], L[u], d, 1, n, 1);    R[u] = dc;}void lca_init(){    for(int k = 0; k < 21; ++k)        for(int i = 1; i <= n; ++i){            fa[i][k+1] = fa[fa[i][k]][k];        }}int lca(int u, int v){    if(dep[u] > dep[v]) swap(u, v);    for(int i = 21; i >= 0; --i){        if((dep[v] - dep[u]) >> i & 1)            v = fa[v][i];    }    if(u == v) return u;    for(int i = 21; i >= 0; --i)        if(fa[u][i] != fa[v][i])            u = fa[u][i], v = fa[v][i];    return fa[u][0];}   bool rt(int x){    return pre[x] == 0 || ch[pre[x]][0] != x && ch[pre[x]][1] != x;}void rot(int x){    int y = pre[x], d = ch[y][1] == x;    if(!rt(y)) ch[pre[y]][ch[pre[y]][1]==y] = x;    ch[y][d] = ch[x][!d];    pre[ch[x][!d]] = y;    ch[x][!d] = y;    pre[x] = pre[y];    pre[y] = x;}void splay(int x){    while(!rt(x)){        int f = pre[x], ff = pre[f];        if(rt(f)) rot(x);        else if((ch[ff][1] == f) == (ch[f][1] == x))            rot(f), rot(x);        else rot(x), rot(x);    }}int find(int x){    while(ch[x][0]) x = ch[x][0];    return x;}void access(int x){    for(int y = 0; x; y = x, x = pre[x]){        splay(x);        if(ch[x][1]){            int p = find(ch[x][1]);            //printf("%d\n", p);            int l = L[p], r = R[p];            update(l, r, 1, 1, n, 1);        }        if(y){            int p = find(y);        //  printf("%d\n", p);            int l = L[p], r = R[p];            update(l, r, -1, 1, n, 1);        }           ch[x][1] = y;    }}int main(){    scanf("%d%d", &n, &m);    init();    for(int i = 1; i < n; ++i){        int u, v;        scanf("%d%d", &u, &v);        add(u, v);        add(v, u);    }    dfs(1, 0, 1);    lca_init();    while(m--){        int op, x, y;        scanf("%d", &op);        if(op == 1){            scanf("%d", &x);            access(x);        }        else if(op == 2){            scanf("%d%d", &x, &y);            int ans = 0, l, r, p = lca(x, y);        //  printf("op2 %d %d %d\n", x, y, p);            l = r = L[x];            ans += query(l, r, 1, n, 1);            l = r = L[y];            ans += query(l, r, 1, n, 1);            l = r = L[p];            ans -= query(l, r, 1, n, 1) * 2;            printf("%d\n", ans + 1);        }        else{            scanf("%d", &x);            int l = L[x], r = R[x];        //  printf("query %d %d %d\n", x, l, r);            printf("%d\n", query(l, r, 1, n, 1));        }    }    return 0;}
0 0
原创粉丝点击