zoukankan      html  css  js  c++  java
  • codeforces 570 D. Tree Requests (dfs)

    题目链接:

      570 D. Tree Requests

    题目描述:

      给出一棵树,有n个节点,1号节点为根节点深度为1。每个节点都有一个字母代替,问以结点x为根的子树中高度为h的后代是否能够经过从新排序变成一个回文串?

    解题思路:

      判断是不是回文串,可以统计集合中出现过的字母的个数,出现奇数次的字母个数小于1,即为回文串,否则不是。所以我们可以使用状压统计当前区间中字母出现的奇偶次数。

      对于如何快速的求出区间,先dfs整棵树,标记下来每个节点进栈的时间和出栈的时间,然后把高度一样的点按照进栈时间顺序升序存在一起。如果节点x的时间戳为(s, e),那么以x为根节点的子树中所有的节点的时间戳都在这个区间内,不在这个子树中的节点的时间戳都不在这个区间内。辣么我们就可以二分高度为h的节点寻找时间戳在(s,e)区间内的节点咯。

      思路是这样的,但是就是一直Runtime error on test 15,有没有很神奇。然后就去tokers的博客膜拜一下,最后代码几乎改成一样的了,但是Runtime error on test 15一直执着的不愿离我而去。一怒之下,全部删光光,重写一边就AC了(┭┮﹏┭┮重写大法好..........)

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int maxn = 500100;
      4 
      5 int L[maxn], R[maxn], rp[maxn];
      6 int dfn, dep[maxn];
      7 char str[maxn];
      8 vector < int > sum[maxn];
      9 vector < int > node[maxn];
     10 vector < int > tree[maxn];
     11 
     12 void dfs (int u)
     13 {
     14     L[u] = ++dfn;
     15     rp[L[u]] = u;
     16     node[dep[u]].push_back(L[u]);
     17     for (int i=0; i<tree[u].size(); i++)
     18     {
     19         int v = tree[u][i];
     20         dep[v] = dep[u] + 1;
     21         dfs (v);
     22     }
     23     R[u] = dfn;
     24 }
     25 
     26 void init (int n)
     27 {
     28     dfn = 0;
     29     dep[1] = 1;
     30     for (int i=1; i<maxn; i++)
     31     {
     32         sum[i].clear();
     33         node[i].clear();
     34         tree[i].clear();
     35     }
     36 }
     37 
     38 int main ()
     39 {
     40     int n, m;
     41     while (scanf ("%d %d", &n, &m) != EOF)
     42     {
     43         init (n);
     44         for (int i=2; i<=n; i++)
     45         {
     46             int v;
     47             scanf ("%d", &v);
     48             tree[v].push_back(i);
     49         }
     50         
     51         dfs (1);
     52         scanf ("%s", str+1);
     53         for (int i=1; i<=n; i++)
     54         {
     55             int size = node[i].size();
     56             for (int j=0; j<size; j++)
     57             {
     58                 sum[i].push_back(0);
     59                 int x = str[rp[node[i][j]]] - 'a';
     60                 sum[i][j] |= (1<<x);
     61             }
     62             for (int j=1; j<size; j++)
     63                 sum[i][j] ^= sum[i][j-1];
     64         }
     65         
     66         int x, h;
     67         while (m --)
     68         {
     69             scanf ("%d %d", &x, &h);
     70             int l, r, size;
     71             l = L[x];
     72             r = R[x];
     73             size = node[h].size();
     74             
     75             if (dep[x]>=h || !size || r<node[h][0] || l>node[h][size-1])
     76             {
     77                 printf ("Yes
    ");
     78                 continue;
     79             }
     80             
     81             int a = lower_bound(node[h].begin(), node[h].end(), l) - node[h].begin();
     82             int b = lower_bound(node[h].begin(), node[h].end(), r) - node[h].begin();
     83             
     84             if (b == size || node[h][b]>r)
     85                 b --;
     86             int res = sum[h][b];
     87             if (a)
     88                 res ^= sum[h][a-1];
     89                 
     90             int ans = 0;
     91             for (int i=0; i<26; i++)
     92             {
     93                 if (res & (1<<i))
     94                     ans ++;
     95             }
     96             
     97             printf ("%s
    ", ans>1?"No":"Yes");
     98         }
     99     }
    100     return 0;
    101 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    第十二章,结束练习
    第十一章,表单
    第十章,表格练习
    第九章,跨行跨列的表格
    第八章,表格
    第七章,列表
    第六章,body当中的属性
    第五章,标签的使用
    6. C# 命名规则
    5. c#变量
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4734724.html
Copyright © 2011-2022 走看看