zoukankan      html  css  js  c++  java
  • [HNOI2014]世界树

    · 题解

      参考hzwer

      首先看到Mi的条件想到构造虚树。

      虚树中的一条边已经覆盖了整个出现在这条边上的点的子树的情况。

      那么只需倍增查找所属议事处有变化的边界节点,同时计算这两段节点的贡献即可。

    · 代码

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <vector>
      5 #include <algorithm>
      6 
      7 using namespace std;
      8 
      9 const int MAXN = 3e05 + 10;
     10 const int MAXM = 3e05 + 10;
     11 
     12 struct LinkedForwardStar {
     13     int to;
     14     
     15     int next;
     16 } ;
     17 
     18 LinkedForwardStar Link[MAXM << 1];
     19 int Head[MAXN]= {0};
     20 int size = 0;
     21 
     22 void Insert (int u, int v) {
     23     Link[++ size].to = v;
     24     Link[size].next = Head[u];
     25     
     26     Head[u] = size;
     27 }
     28 
     29 const int Root = 1;
     30 
     31 int Deep[MAXN];
     32 
     33 int Size[MAXN];
     34 
     35 int Dfn[MAXN];
     36 int dfsord = 0;
     37 
     38 int Father[MAXN][23];
     39 
     40 void DFS (int root, int father) {
     41     Dfn[root] = ++ dfsord;
     42     Size[root] = 1;
     43     Father[root][0] = father;
     44     for (int j = 1; j <= 20; j ++) {
     45         if (! Father[root][j - 1])
     46             continue;
     47         
     48         Father[root][j] = Father[Father[root][j - 1]][j - 1];
     49     }
     50     
     51     for (int i = Head[root]; i; i = Link[i].next) {
     52         int v = Link[i].to;
     53         
     54         if (v == father)
     55             continue;
     56         
     57         Deep[v] = Deep[root] + 1;
     58         
     59         DFS (v, root);
     60         
     61         Size[root] += Size[v];
     62     }
     63 }
     64 
     65 int LCA (int x, int y) {
     66     if (Deep[x] < Deep[y])
     67         swap (x, y);
     68     
     69     int fx = x, fy = y;
     70     for (int j = 20; j >= 0; j --)
     71         if (Deep[Father[fx][j]] >= Deep[fy])
     72             fx = Father[fx][j];
     73     
     74     if (fx == fy)
     75         return fy;
     76     
     77     for (int j = 20; j >= 0; j --)
     78         if (Father[fx][j] != Father[fy][j]) {
     79             fx = Father[fx][j];
     80             fy = Father[fy][j];
     81         }
     82     
     83     return Father[fx][0];
     84 }
     85 
     86 int Dist (int x, int y) {
     87     int lca = LCA (x, y);
     88     return Deep[x] + Deep[y] - 2 * Deep[lca];
     89 }
     90 
     91 int N, Q;
     92 
     93 int A[MAXN];
     94 
     95 vector<int> Graph[MAXN];
     96 
     97 int Stack[MAXN];
     98 int top = 0;
     99 
    100 int Belong[MAXN]= {0};
    101 
    102 bool comp (const int& a, const int& b) {
    103     return Dfn[a] < Dfn[b];
    104 }
    105 
    106 void Insert_IvTree (int p) {
    107     if (! top) {
    108         Stack[++ top] = p;
    109         
    110         return ;
    111     }
    112     
    113     int lca = 0;
    114     while (top > 0) {
    115         lca = LCA (Stack[top], p);
    116         if (top > 1 && Deep[lca] < Deep[Stack[top - 1]])
    117             Graph[Stack[top - 1]].push_back(Stack[top]), top --;
    118         else if (Deep[lca] < Deep[Stack[top]]) {
    119             Graph[lca].push_back(Stack[top]), top --;
    120             break;
    121         }
    122         else
    123             break;
    124     }
    125     
    126     if (Stack[top] != lca)
    127         Stack[++ top] = lca;
    128     Stack[++ top] = p;
    129 }
    130 
    131 int M;
    132 
    133 void Construct () {
    134     top = 0;
    135     if (Belong[Root] != Root)
    136         Stack[++ top] = Root;
    137     
    138     sort (A + 1, A + M + 1, comp);
    139     
    140     for (int i = 1; i <= M; i ++)
    141         Insert_IvTree (A[i]);
    142     while (top > 1)
    143         Graph[Stack[top - 1]].push_back(Stack[top]), top --;
    144 }
    145 
    146 int Rank[MAXN]= {0};
    147 
    148 int Rest[MAXN]= {0};
    149 
    150 void Get_BelSon (int root) {
    151     Rank[++ dfsord] = root;
    152     Rest[root] = Size[root];
    153     
    154     for (int i = 0; i < Graph[root].size(); i ++) {
    155         int v = Graph[root][i];
    156         
    157         Get_BelSon (v);
    158         
    159         if (! Belong[v])
    160             continue;
    161         
    162         int dist1 = Dist (Belong[root], root), dist2 = Dist (Belong[v], root);
    163         if (! Belong[root] || dist1 > dist2 || (dist1 == dist2 && Belong[root] > Belong[v]))
    164             Belong[root] = Belong[v];
    165     }
    166 }
    167 
    168 void Get_BelFat (int root) {
    169     for (int i = 0; i < Graph[root].size(); i ++) {
    170         int v = Graph[root][i];
    171         
    172         int dist1 = Dist (Belong[root], v), dist2 = Dist (Belong[v], v);
    173         if (! Belong[v] || dist1 < dist2 || (dist1 == dist2 && Belong[root] < Belong[v]))
    174             Belong[v] = Belong[root];
    175         
    176         Get_BelFat (v);
    177     }
    178 }
    179 
    180 int Count[MAXN]= {0};
    181 
    182 void Calc (int u, int v) {
    183     int p = v;
    184     for (int j = 20; j >= 0; j --)
    185         if (Deep[Father[p][j]] > Deep[u])
    186             p = Father[p][j];
    187     
    188     Rest[u] -= Size[p];
    189     
    190     if (Belong[u] == Belong[v]) {
    191         Count[Belong[u]] += Size[p] - Size[v];
    192         return ;
    193     }
    194     
    195     int mid = v;
    196     for (int j = 20; j >= 0; j --) {
    197         if (Deep[Father[mid][j]] <= Deep[u])
    198             continue;
    199         
    200         int nextpos = Father[mid][j];
    201         int dist1 = Dist (Belong[v], nextpos), dist2 = Dist (Belong[u], nextpos);
    202         if (dist1 < dist2 || (dist1 == dist2 && Belong[v] < Belong[u]))
    203             mid = nextpos;
    204     }
    205     
    206     Count[Belong[u]] += Size[p] - Size[mid];
    207     Count[Belong[v]] += Size[mid] - Size[v];
    208 }
    209 
    210 int getnum () {
    211     int num = 0;
    212     char ch = getchar ();
    213     
    214     while (! isdigit (ch))
    215         ch = getchar ();
    216     while (isdigit (ch))
    217         num = num * 10 + ch - '0', ch = getchar ();
    218     
    219     return num;
    220 }
    221 
    222 int Orig[MAXN];
    223 
    224 void Solve () {
    225     M = getnum ();
    226     
    227     for (int i = 1; i <= M; i ++)
    228         A[i] = Orig[i] = getnum ();
    229     
    230     for (int i = 1; i <= M; i ++)
    231         Belong[A[i]] = A[i];
    232     
    233     Construct ();
    234     
    235     dfsord = 0;
    236     Get_BelSon (Root), Get_BelFat (Root);
    237     
    238     for (int i = 1; i <= dfsord; i ++) {
    239         int u = Rank[i];
    240         for (int j = 0; j < Graph[u].size(); j ++) {
    241             int v = Graph[u][j];
    242             Calc (u, v);
    243         }
    244     }
    245     
    246     for (int i = 1; i <= dfsord; i ++)
    247         Count[Belong[Rank[i]]] += Rest[Rank[i]];
    248     
    249     for (int i = 1; i <= M; i ++) {
    250         if (i > 1)
    251             putchar (' ');
    252         printf ("%d", Count[Orig[i]]);
    253     }
    254     puts ("");
    255     
    256     for (int i = 1; i <= dfsord; i ++) {
    257         Graph[Rank[i]].clear();
    258         Count[Rank[i]] = Belong[Rank[i]] = Rest[Rank[i]] = 0;
    259     }
    260 }
    261 
    262 int main () {
    263     N = getnum ();
    264     
    265     for (int i = 1; i < N; i ++) {
    266         int u, v;
    267         u = getnum (), v = getnum ();
    268         
    269         Insert (u, v), Insert (v, u);
    270     }
    271     
    272     Deep[Root] = 1;
    273     DFS (Root, 0);
    274     
    275     Q = getnum ();
    276     
    277     for (int Case = 1; Case <= Q; Case ++)
    278         Solve ();
    279     
    280     return 0;
    281 }
    282 
    283 /*
    284 10
    285 2 1
    286 3 2
    287 4 3
    288 5 4
    289 6 1
    290 7 3
    291 8 3
    292 9 4
    293 10 1
    294 5
    295 2
    296 6 1
    297 5
    298 2 7 3 6 9
    299 1
    300 8
    301 4
    302 8 7 10 3
    303 5
    304 2 9 3 5 8
    305 */
    View Code
  • 相关阅读:
    Ubuntu里Eclipse关联Jdk
    解决Ubuntu自带编译器不好使问题
    Ubuntu英文变为中文
    两个VirtualBox版本装的语言不一样?
    Hadoop-2.0 目录简介
    Eclipse项目里面看源码和文档
    Eclipse搭建Struts2环境
    2017,崭新的一年!
    cl-closure-template 中文乱码的解决方法
    common-list基础知识--多值的返回与接收
  • 原文地址:https://www.cnblogs.com/Colythme/p/9745928.html
Copyright © 2011-2022 走看看