CodeForces 825G"Tree Queries"(選根建樹)

 

傳送門ios

 

•參考資料

  [1]:CodeForces 825G Educational Round #25 G :建樹選根大法+O1大法+iostream解綁了仍是慢c++

•題意

  給定一顆包含 n 個節點的樹,開始樹的全部節點都是白色的;ide

  給出 q 次詢問,詢問分爲一、2兩種:ui

    1. 將節點 x 塗成黑色。
    2. 詢問節點 x 到全部的黑點節點的簡單路徑中的標號最小的那個點(包括起點和黑點)

  題目保證第一次詢問是 1 類型的。url

•題解

  若是咱們隨便選取某節點做爲根節點,那麼詢問的時候,咱們要找到節點 x 到全部黑色節點的 LCA;spa

  可是這樣顯然會超時的,因此咱們換一種建樹方法。3d

  因爲第一個詢問必然是 1 類型,那麼咱們就把第一次詢問的那個變黑的點做爲根節點,看一下這樣有什麼好處;code

  定義 $res_i$ 表示節點 i 到根節點(詢問1的x)的路徑中,標號最小的節點;blog

  首先,咱們預處理出全部的 $res$,只需 $DFS$ 一遍便可,時間複雜度 $O(n)$;get

  接下來,若是剩餘的詢問所有是 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\n",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
相關文章
相關標籤/搜索