[BZOJ4551][Tjoi2016&Heoi2016]树 dfs序+线段树

来源:互联网 发布:mac 任务管理工具 编辑:程序博客网 时间:2024/06/05 04:16

维护一棵只有标记的线段树
标记为二元组(x,v)表示节点和深度
定义标记加法为取v较大的那个标记

#include <iostream>#include <cstdio>#include <vector>#define mid ( (l + r) >> 1 )#define ls l,mid,t<<1#define rs mid+1,r,t<<1^1 #define N 100050using namespace std;vector<int> e[N];int L[N],R[N],vis[N],dep[N];int tme,ll,rr,x,ans,n,q;void dfs(int u) {    vis[u] = 1; L[u] = ++tme;    for (int i=0;i<(int)e[u].size();i++) {        int v = e[u][i]; if (vis[v]) continue;        dep[v] = dep[u] + 1; dfs(v);    }    R[u] = tme;}struct Tag{ int x,v; }ag[4*N],v;Tag operator+(Tag p1,Tag p2) { return p1.v > p2.v ? p1 : p2; }void push_down(int t) {    ag[t<<1] = ag[t<<1] + ag[t];    ag[t<<1^1] = ag[t<<1^1] + ag[t];}void update(int l,int r,int t) {    if (l > rr || r < ll) return ;    if (l >= ll && r <= rr) { ag[t] = ag[t] + v; return ; }    push_down(t); update(ls); update(rs);}void query(int l,int r,int t) {    if (l > x || r < x) return ;    if (l == r) { ans = ag[t].x; return ; }    push_down(t); query(ls); query(rs);}int main() {    scanf("%d%d",&n,&q);    for (int i=1;i<=n-1;i++) {        int u,v; scanf("%d%d",&u,&v);        e[u].push_back(v);        e[v].push_back(u);    }    dep[1] = 1; dfs(1); ag[1] = (Tag){1,1};    while (q--) {        char cmd[10];        scanf("%s%d",cmd+1,&x);        if (cmd[1] == 'C') {            ll = L[x] , rr = R[x] , v = (Tag){x,dep[x]};            update(1,n,1);          } else {            x = L[x] , query(1,n,1); printf("%d\n",ans);        }    }    return 0;} 
0 0