zoukankan      html  css  js  c++  java
  • CodeForces 825G"Tree Queries"(选根建树)

    传送门

    •参考资料

      [1]:CodeForces 825G Educational Round #25 G :建树选根大法+O1大法+iostream解绑了还是慢

    •题意

      给定一颗包含 n 个节点的树,开始树的所有节点都是白色的;

      给出 q 次询问,询问分为1、2两种:

      1. 将节点 x 涂成黑色。
      2. 询问节点 x 到所有的黑点节点的简单路径中的标号最小的那个点(包括起点和黑点)

      题目保证第一次询问是 1 类型的。

    •题解

      如果我们随便选取某节点作为根节点,那么询问的时候,我们要找到节点 x 到所有黑色节点的 LCA;

      但是这样显然会超时的,所以我们换一种建树方法。

      由于第一个询问必然是 1 类型,那么我们就把第一次询问的那个变黑的点作为根节点,看一下这样有什么好处;

      定义 $res_i$ 表示节点 i 到根节点(询问1的x)的路径中,标号最小的节点;

      首先,我们预处理出所有的 $res$,只需 $DFS$ 一遍即可,时间复杂度 $O(n)$;

      接下来,如果剩余的询问全部是 2 类型,那么,对于节点 x 的询问,直接输出 $res_x$ 即可;

      但是,如果存在 1 类型的询问呢?

      对于新的黑色节点 $u_1,u_2,.....$,在查询节点 x 的时候,除了需要知道节点 x 到根节点路径上标号最小的节点;

      同时还需要求出节点 x 到黑色节点 $u_i$ 路径上标号最小的节点;

      你会发现,求解节点 x 到黑色节点 $u_i$ 路径上的标号最小的节点等价于求解根节点到黑色节点 $u_i$ 路径上的标号最小的节点;

      那这么说的话,我们就可以定义一个变量 $Min$,用来存储新加入的黑色节点到根节点的路径上标号最小的节点信息;

      询问的时候,只需输出 $res_x$ 和 $Min$ 的最小值即可; 

    •Code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define INF 0x3f3f3f3f
     4 #define mem(a,b) memset(a,b,sizeof(a))
     5 const int maxn=1e6+50;
     6 
     7 int n,q;
     8 int num;
     9 int head[maxn];
    10 struct Edge
    11 {
    12     int to;
    13     int next;
    14 }G[maxn<<1];
    15 void addEdge(int u,int v)
    16 {
    17     G[num]={v,head[u]};
    18     head[u]=num++;
    19 }
    20 int res[maxn];
    21 
    22 void DFS(int u,int f)
    23 {
    24     res[u]=min(u,res[f]);
    25     for(int i=head[u];~i;i=G[i].next)
    26     {
    27         int v=G[i].to;
    28         if(v != f)
    29             DFS(v,u);
    30     }
    31 }
    32 void Solve()
    33 {
    34     mem(res,INF);
    35 
    36     int ans=0;
    37     int Min=INF;
    38     for(int i=1;i <= q;++i)
    39     {
    40         int t,z;
    41         scanf("%d%d",&t,&z);
    42         int x=(z+ans)%n+1;
    43 
    44         if(i == 1)
    45             DFS(x,x);
    46         else if(t == 1)
    47             Min=min(Min,res[x]);
    48         else
    49         {
    50             ans=min(Min,res[x]);
    51             printf("%d
    ",ans);
    52         }
    53     }
    54 }
    55 void Init()
    56 {
    57     num=0;
    58     mem(head,-1);
    59 }
    60 int main()
    61 {
    62     Init();
    63     scanf("%d%d",&n,&q);
    64     for(int i=1;i < n;++i)
    65     {
    66         int u,v;
    67         scanf("%d%d",&u,&v);
    68         addEdge(u,v);
    69         addEdge(v,u);
    70     }
    71     Solve();
    72 
    73     return 0;
    74 }
    View Code
  • 相关阅读:
    洛谷P1441 砝码称重(搜索,dfs+bitset优化)
    洛谷P1441 砝码称重(搜索,dfs+dp)
    洛谷P1242 新汉诺塔(dfs,模拟退火)
    洛谷P1415 拆分数列(dp)
    openstack-往已有集群中添加控制节点,实现控制节点的高可用
    第九步:使用nfs作为cinder-controller后端存储
    第八步:安装openstack-dashboard
    第七步(2):安装openstack-cinder服务-控制节点
    第七步(1):安装openstack-cinder服务-存储节点
    第六步:创建实例进行测试
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/11733860.html
Copyright © 2011-2022 走看看