CodeForces - 343D 树链剖分

Posted キリト

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 343D 树链剖分相关的知识,希望对你有一定的参考价值。

 

题目链接:http://codeforces.com/problemset/problem/343/D

题意:给定一棵n个n-1条边的树,起初所有节点权值为0,然后m个操作。 1 x:把x为根的子树的点的权值修改为1; 2 x:把x结点到根路径上的点修改为0; 3 x:查询结点x的值。

思路:树链剖分。 对于操作1,子树操作记录下当前点为根时,dfs的最后一个点的id是多少(endid[]),然后就可以把子树操作用区间来维护了。 对于操作2,树链剖分。 对于3操作,线段树单点查询。

 

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<time.h>
#include<cmath>
#include<sstream>
#include<assert.h>
using namespace std;
#define L(x) x<<1
#define R(x) x<<1|1
typedef long long int LL;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
const int MAXN = 500000 + 10;
int head[MAXN], tot, cnt;
struct Edge{
    int to, next;
}Edges[MAXN * 2];
void add(int u, int v){
    Edges[tot].to = v;
    Edges[tot].next = head[u];
    head[u] = tot++;
}
int id[MAXN], endid[MAXN],son[MAXN], deep[MAXN], size[MAXN], fa[MAXN], reid[MAXN], top[MAXN];
void Init(){
    tot = 0; cnt = 0;
    memset(head, -1, sizeof(head));
    memset(son, -1, sizeof(son));
}
void DFS1(int u, int p,int dep){
    fa[u] = p; size[u] = 1; deep[u] = dep;
    for (int i = head[u]; i != -1; i = Edges[i].next){
        if (Edges[i].to != p){
            DFS1(Edges[i].to, u,dep+1);
            size[u] += size[Edges[i].to];
            if (son[u] == -1 || size[Edges[i].to] > size[son[u]]){
                son[u] = Edges[i].to;
            }
        }
    }
}
void DFS2(int u, int tp){
    id[u] = ++cnt; reid[id[u]] = u; top[u] = tp;
    if (son[u] == -1){ endid[u] = cnt; return; }
    DFS2(son[u], tp);
    for (int i = head[u]; i != -1; i = Edges[i].next){
        if (son[u] != Edges[i].to&&Edges[i].to != fa[u]){
            DFS2(Edges[i].to, Edges[i].to);
        }
    }
    endid[u] = cnt;
}
struct Node{
    int st, ed;
    int lazy,val;
}Seg[MAXN * 4];
void pushDown(int k){
    if (Seg[k].lazy!=-1){
        Seg[L(k)].lazy = Seg[L(k)].val = Seg[k].lazy;
        Seg[R(k)].lazy = Seg[R(k)].val = Seg[k].lazy;
        Seg[k].lazy = -1;
    }
}
void Build(int l, int r, int k){
    Seg[k].st = l; Seg[k].ed = r;  Seg[k].lazy = -1; Seg[k].val = 0;
    if (l == r){
        return;
    }
    int mid = (l + r) / 2;
    Build(l, mid, L(k)); Build(mid + 1, r, R(k));
}
void Modify(int l,int r,int val,int k){ 
    if (Seg[k].st == l&&Seg[k].ed == r){
        Seg[k].lazy = Seg[k].val = val;
        return;
    }
    pushDown(k);
    if (r <= Seg[L(k)].ed){
        Modify(l, r, val, L(k));
    }
    else if (l >= Seg[R(k)].st){
        Modify(l, r, val, R(k));
    }
    else{
        Modify(l, Seg[L(k)].ed, val, L(k));
        Modify(Seg[R(k)].st, r, val, R(k));
    }
}
void Modify(int u, int v,int val){
    int f1 = top[u], f2 = top[v];
    while (f1 != f2){
        if (deep[f1] < deep[f2]){
            swap(f1, f2);
            swap(u, v);
        }
        Modify(id[f1], id[u], val,1);
        u = fa[f1]; f1 = top[u];
    }
    if (deep[u] > deep[v]){
        swap(u, v);
    }
    Modify(id[u], id[v],val, 1);
}
int Query(int pos, int k){ 
    if (Seg[k].st == Seg[k].ed){
        return Seg[k].val;
    }
    pushDown(k);
    if (pos <= Seg[L(k)].ed){
        return Query(pos, L(k));
    }
    else{
        return Query(pos, R(k));
    }
}
int main(){
//#ifdef kirito
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//#endif
//    int start = clock();
    int n,m;
    while (~scanf("%d",&n)){
        Init();
        for (int i = 1; i < n; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v); add(v, u);
        }
        DFS1(1, 1, 0);  DFS2(1, 1); Build(1, n, 1);
        scanf("%d", &m);
        while (m--){
            int u, v;
            scanf("%d%d", &u, &v);
            switch (u){
            case 1: Modify(id[v], endid[v], 1, 1); break;
            case 2: Modify(v, 1, 0); break;
            default: printf("%d\n", Query(id[v], 1)); break;
            }
        }
    }
//#ifdef LOCAL_TIME
//    cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
    return 0;
}

 

以上是关于CodeForces - 343D 树链剖分的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 343D Water Tree & 树链剖分教程

codeforces 343D Water Tree 树链剖分 dfs序 线段树 set

CF343D Water Tree 树链剖分

CodeForces 191C 树链剖分 第4遍

Codeforces Round #425 (Div. 2) D 树链剖分 + 树状数组维护区间

D. Happy Tree Party CodeForces 593D树链剖分,树边权转点权