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 }
  • 相关阅读:
    我要好offer之 二叉树大总结
    我要好offer之 字符串相关大总结
    楼层扔鸡蛋问题[转]
    Linux System Programming 学习笔记(十一) 时间
    Linux System Programming 学习笔记(十) 信号
    Linux System Programming 学习笔记(九) 内存管理
    Linux System Programming 学习笔记(八) 文件和目录管理
    Linux System Programming 学习笔记(七) 线程
    Linux System Programming 学习笔记(六) 进程调度
    APUE 学习笔记(十一) 网络IPC:套接字
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6428647.html
Copyright © 2011-2022 走看看