zoukankan      html  css  js  c++  java
  • 【并查集】BZOJ4551-[Tjoi2016&Heoi2016]树

    NOIP太可怕了((( -口-)

    题目链接

    【题目大意】

    给定一颗有根树(根为1),有以下两种操作:

    1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个结点,可以打多次标记。)

    2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖先)
     
    【思路】
    正着做不行就反方向来。先离线处理所有操作,算出最终某个点被标记了几次。跑一次dfs算出最终状态时每个点最近的打了标记的祖先u[i]。
    从后往前重新看操作,如果是标记操作,那么当前节点标记数-1,如果标记数为0了,那么u[i]=fa[i]最近的祖先(用并查集来处理之前的更新)。如果为询问,则输出当前最近的祖先(同样可以用并查集来做)。
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAXN=100000+50;
     4 vector<int> E[MAXN];
     5 int mark[MAXN];
     6 int query[MAXN],ans[MAXN]; 
     7 int u[MAXN],fa[MAXN],n,q;
     8 char op[MAXN];
     9 
    10 void dfs(int x,int anc,int father)
    11 {
    12     fa[x]=father;
    13     if (mark[x]>0) u[x]=x;
    14         else u[x]=anc;
    15     for (int i=0;i<E[x].size();i++)
    16     {
    17         int to=E[x][i];
    18         if (to==fa[x]) continue;
    19         dfs(to,u[x],x);
    20     }
    21 }
    22 
    23 int union_set(int x)
    24 {
    25     int r=x;
    26     while (u[r]!=r) r=u[r];
    27     int now=x;
    28     while (u[now]!=r)
    29     {
    30         int tmp=u[now];
    31         u[now]=r;
    32         now=tmp;
    33     }
    34     return u[x];
    35 }
    36 
    37 void init()
    38 {
    39     scanf("%d%d",&n,&q);
    40     for (int i=1;i<n;i++)
    41     {
    42         int u,v;
    43         scanf("%d%d",&u,&v);
    44         E[u].push_back(v);
    45         E[v].push_back(u);
    46     }
    47     mark[1]=1;
    48     for (int i=1;i<=q;i++)
    49     {
    50         char tmp[1];
    51         scanf("%s %d",tmp,&query[i]);
    52         if (tmp[0]=='C') mark[query[i]]++;
    53         op[i]=tmp[0];
    54     }
    55     dfs(1,1,0);
    56     for (int i=1;i<=n;i++) cout<<u[i]<<endl;
    57 }
    58 
    59 void solve()
    60 {
    61     memset(ans,0,sizeof(ans));
    62     for (int i=q;i>=1;i--)
    63     {
    64         int now=query[i];
    65         if (op[i]=='C')
    66         {
    67             mark[now]--;
    68             if (!mark[now]) now=union_set(fa[now]);
    69         }
    70         else ans[++ans[0]]=union_set(now);
    71     }    
    72     for (int i=ans[0];i>=1;i--) printf("%d
    ",ans[i]);
    73 } 
    74 
    75 int main()
    76 {
    77     init();
    78     solve();
    79     return 0;
    80 }
  • 相关阅读:
    watchers
    Observer
    计算属性
    Jsonp
    跨域
    axios
    duilib入门简明教程 -- 部分bug (11) (转)
    duilib入门简明教程 -- 界面设计器 DuiDesigner (10) (转)
    duilib入门简明教程 -- 界面布局(9) (转)
    duilib入门简明教程 -- 完整的自绘标题栏(8) (转)
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/6080809.html
Copyright © 2011-2022 走看看