zoukankan      html  css  js  c++  java
  • bzoj4551 [Tjoi2016&Heoi2016]树

    Description

    在2016年,佳媛姐姐刚刚学习了树,非常开心。现在他想解决这样一个问题:给定一颗有根树(根为1),有以下两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个结点,可以打多次标记。)2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖先)你能帮帮他吗?

    Input

    输入第一行两个正整数N和Q分别表示节点个数和操作次数接下来N-1行,每行两个正整数u,v(1≤u,v≤n)表示u到v有一条有向边接下来Q行,形如“opernum”oper为“C”时表示这是一个标记操作,oper为“Q”时表示这是一个询问操作对于每次询问操作,1 ≤ N, Q ≤ 100000。

    Output

    输出一个正整数,表示结果

    Sample Input

    5 5
    1 2
    1 3
    2 4
    2 5
    Q 2
    C 2
    Q 2
    Q 5
    Q 3

    Sample Output

    1
    2
    2
    1

    HINT

     新加数据9组(By HFLSyzx ),未重测--2016.8.2

    正解:并查集。

    考虑离线倒序处理,先把标记结点和它的子树合并,然后处理询问时查询就输出值就好,打标记的话就是要把当前标记去掉,那么只要当前这个点没有标记了就把它和它父亲合并。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define il inline
    15 #define RG register
    16 #define ll long long
    17   
    18 using namespace std;
    19   
    20 struct edge{ int nt,to; }g[2000010];
    21 struct node{ int d,x; }q[1000010];
    22   
    23 int head[1000010],fa[1000010],f[1000010],cnt[1000010],ans[1000010],n,Q,num;
    24 char s[5];
    25   
    26 il int gi(){
    27     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    28     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    29 }
    30   
    31 il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; }
    32   
    33 il int find(RG int x){ return f[x]==x ? f[x] : f[x]=find(f[x]); }
    34   
    35 il void unionn(RG int u,RG int v){ f[find(u)]=find(v); return; }
    36   
    37 il void dfs(RG int x,RG int p){
    38     fa[x]=p; RG int v;
    39     for (RG int i=head[x];i;i=g[i].nt){
    40     v=g[i].to; if (v==p) continue;
    41     dfs(v,x); if (!cnt[v]) unionn(v,x);
    42     }
    43     return;
    44 }
    45   
    46 il void work(){
    47     n=gi(),Q=gi(); RG int u,v,x; cnt[1]=1; f[n]=n;
    48     for (RG int i=1;i<n;++i) f[i]=i,u=gi(),v=gi(),insert(u,v),insert(v,u);
    49     for (RG int i=1;i<=Q;++i){
    50     scanf("%s",s); x=gi();
    51     if (s[0]=='C') q[i].d=1,q[i].x=x,cnt[x]++;
    52     if (s[0]=='Q') q[i].d=2,q[i].x=x;
    53     }
    54     dfs(1,0); RG int tot=0;
    55     for (RG int i=Q;i;--i){
    56     if (q[i].d==1){ cnt[q[i].x]--; if (!cnt[q[i].x]) unionn(q[i].x,fa[q[i].x]); }
    57     if (q[i].d==2) ans[++tot]=find(q[i].x);
    58     }
    59     for (RG int i=tot;i;--i) printf("%d
    ",ans[i]); return;
    60 }
    61   
    62 int main(){
    63     work();
    64     return 0;
    65 }
  • 相关阅读:
    Python 的并发编程
    django搭建一个小型的服务器运维网站-拿来即用的bootstrap模板
    python 文件目录遍历
    Ubuntu 18.04 登陆界面进去,几秒之后自动退出到登陆界面
    terminal 快捷操作
    Boost 源代码交叉编译
    tar 常见操作
    vim 快捷设置和操作
    Visual Studio Linker选项设置
    5. glutInitDisplayMode 函数理解
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6428647.html
Copyright © 2011-2022 走看看