题目链接:

题目

D. Tree Requests
time limit per test:2 seconds
memory limit per test:256 megabytes

问题描述

Roman planted a tree consisting of n vertices. Each vertex contains a lowercase English letter. Vertex 1 is the root of the tree, each of the n - 1 remaining vertices has a parent in the tree. Vertex is connected with its parent by an edge. The parent of vertex i is vertex pi, the parent index is always less than the index of the vertex (i.e., pi < i).

The depth of the vertex is the number of nodes on the path from the root to v along the edges. In particular, the depth of the root is equal to 1.

We say that vertex u is in the subtree of vertex v, if we can get from u to v, moving from the vertex to the parent. In particular, vertex v is in its subtree.

Roma gives you m queries, the i-th of which consists of two numbers vi, hi. Let's consider the vertices in the subtree vi located at depth hi. Determine whether you can use the letters written at these vertices to make a string that is a palindrome. The letters that are written in the vertexes, can be rearranged in any order to make a palindrome, but all letters should be used.

输入

The first line contains two integers n, m (1 ≤ n, m ≤ 500 000) — the number of nodes in the tree and queries, respectively.

The following line contains n - 1 integers p2, p3, ..., pn — the parents of vertices from the second to the n-th (1 ≤ pi < i).

The next line contains n lowercase English letters, the i-th of these letters is written on vertex i.

Next m lines describe the queries, the i-th line contains two numbers vi, hi (1 ≤ vi, hi ≤ n) — the vertex and the depth that appear in the i-th query.

输出

Print m lines. In the i-th line print "Yes" (without the quotes), if in the i-th query you can make a palindrome from the letters written on the vertices, otherwise print "No" (without the quotes).

样例

input
6 5
1 1 1 3 3
zacccd
1 1
3 3
4 1
6 1
1 2

output
Yes
No
Yes
Yes
Yes

Note

String s is a palindrome if reads the same from left to right and from right to left. In particular, an empty string is a palindrome.

Clarification for the sample test.

In the first query there exists only a vertex 1 satisfying all the conditions, we can form a palindrome "z".

In the second query vertices 5 and 6 satisfy condititions, they contain letters "с" and "d" respectively. It is impossible to form a palindrome of them.

In the third query there exist no vertices at depth 1 and in subtree of 4. We may form an empty palindrome.

In the fourth query there exist no vertices in subtree of 6 at depth 1. We may form an empty palindrome.

In the fifth query there vertices 2, 3 and 4 satisfying all conditions above, they contain letters "a", "c" and "c". We may form a palindrome "cac".

题意

给你一颗有根树(根节点为1),每个节点有一个字母,回答m个询问,每个询问有两个变量v,h,求深度为h的并且为以v为根的子树的所有节点能否构成回文串(可以任意排列)

题解

回文串的判定:当出现为奇数的字母不超过1个的时候,可以构成回文串。
字母的存储:我们可以把26个字母压到二进制数的26位

1、离线:
开ans[]数组,ans[i]存放第i次查询的结果。
开pre[]数组,pre[h]表示深度为i的在dfs过程中当前已经访问过的所有节点的字母的异或值,那么对于第i次询问v,h我们只要在开始访问(前序遍历到)v的时候,ans[i]^=pre[h]。在结束访问(后续遍历到)v的时候ans[i]^=pre[h],那么,我们就得到第i次询问的结果了!!!

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#define X first
#define Y second
#define mp make_pair
using namespace std;const int maxn = 5e5 + 10;vector<int> G[maxn];
vector<pair<int, int> > que[maxn];
char str[maxn];
int pre[maxn],ans[maxn];
int n, m;void dfs(int u, int dep) {for (int i = 0; i < que[u].size(); i++) {ans[que[u][i].X] ^= pre[que[u][i].Y];}for (int i = 0; i < G[u].size(); i++) {int v = G[u][i];dfs(v, dep + 1);}pre[dep] ^= (1 << (str[u] - 'a'));for (int i = 0; i < que[u].size(); i++) {ans[que[u][i].X] ^= pre[que[u][i].Y];}
}void init() {memset(pre, 0, sizeof(pre));memset(ans, 0, sizeof(ans));
}int main() {init();scanf("%d%d", &n, &m);for (int i = 2; i <= n; i++) {int x; scanf("%d", &x);G[x].push_back(i);}scanf("%s", str + 1);for (int i = 0; i < m; i++) {int v, h; scanf("%d%d", &v, &h);que[v].push_back(mp(i, h));}dfs(1, 1);for (int i = 0; i < m; i++) {if (ans[i] & (ans[i] - 1)) {puts("No");}else puts("Yes");}return 0;
}

2、在线:
首先,我们求树的dfs序,in[maxn]和out[maxn];
我们开vector depth[d]保存所有在深度d的字母的前缀异或和(把每个字母所在的节点的out[]序也丢进去。 (注意:out[]值小的节点一定会先扔进去)
这样,当要处理查询v,h的时候,对于v的子树节点,它们的out序在depth[h]里面必定是连续的一段,我们只要通过二分就能找出这一段的开始和终止的位置(注意这里的开始是指开始访问的前一个)那么我们只要异或一下开始和终止的位置的,得到的就是我们要的结果了。

对于得到的结果ans,ans&(ans-1)就可以判断1的个数是否<=1了。

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define X first
#define Y second
#define mp make_pair
using namespace std;const int maxn = 5e5 + 10;vector<int> G[maxn];
vector<pair<int, int> > dep[maxn];
char str[maxn];
int ans[maxn];
int n, m;int in[maxn], out[maxn],dfs_clock;
void dfs(int u, int d) {in[u] = dfs_clock++;for (int i = 0; i < G[u].size(); i++) {int v = G[u][i];dfs(v, d + 1);}dep[d].push_back(mp(dfs_clock,dep[d].back().Y^(1<<(str[u]-'a'))));out[u] = dfs_clock++;
}void init() {memset(ans, 0, sizeof(ans));dfs_clock = 1;for (int i = 0; i < maxn; i++) {dep[i].push_back(mp(0, 0));}
}int main() {init();scanf("%d%d", &n, &m);for (int i = 2; i <= n; i++) {int x; scanf("%d", &x);G[x].push_back(i);}scanf("%s", str + 1);dfs(1, 1);for (int i = 0; i < m; i++) {int v, d; scanf("%d%d", &v, &d);int l = lower_bound(dep[d].begin(), dep[d].end(), mp(in[v], -1)) - dep[d].begin() - 1;int r = lower_bound(dep[d].begin(), dep[d].end(), mp(out[v], -1)) - dep[d].begin() - 1;ans[i] = dep[d][l].Y ^ dep[d][r].Y;if (ans[i] & (ans[i] - 1)) puts("No");else puts("Yes");}return 0;
}

转载于:https://www.cnblogs.com/fenice/p/5671859.html

Codeforces Round #316 (Div. 2) D. Tree Requests dfs序相关推荐

  1. Codeforces Round #646 (Div. 2)E. Tree Shuffling 题解(dfs)

    题目链接 题目大意 给你一颗树,每一个节点有一个a[i],b[i],c[i]值,你要把b[i]变成c[i],b[i]和c[i]为[0,1],你操作的方法是,选择一个节点x,选择他的k个子树,然后进行交 ...

  2. 570D Codeforces Round #316 (Div. 2) D(dfs序,时间戳,二分

    题目:一棵树上每个节点有个字符值,询问每个节点的深度为h的子节点的字符是否能组成一个回文串. 思路:首先是奇妙的dfs序和时间戳,通过记录每个节点的dfs进出时间,可以发现某个节点的子节点的进出时间均 ...

  3. Codeforces Round #506 (Div. 3) - E. Tree with Small Distances

    题目链接 题意 给你一棵树,最多加几条边,使点1到所有的点的最大距离不超过2 AC 贪心 从距离最远的点开始,找到他的父节点,然后把父节点相连的点删去,这样最好的情况可以删除三层点 遍历树的时候有两种 ...

  4. Codeforces Round #607 (Div. 2) E. Jeremy Bearimy dfs + 思维

    传送门 文章目录 题意: 思路: 题意: 给你2∗k2*k2∗k个点的一棵树.定义GGG为任选kkk组不同的点,每组点的距离和的最小值.定义BBB为任选kkk组不同的点,每组点的距离和的最大值.让你求 ...

  5. Codeforces Round #801 (Div. 2) D2(思维/dfs)

    传送门 题意:给你一颗树,问最少取几点并且得知其与未知点x的距离可以确定树中任意x是哪个节点. 思考:观察可知,对于叶子节点,其兄弟节点到父节点所在的路径上都有点被取到时,不用取它也可以知道具体是哪个 ...

  6. Codeforces Round #499 (Div. 1) Solution

    Codeforces Round #499 (Div. 1) Solution https://codeforces.com/contest/1010 为啥我\(\rm Div.1\)能\(A4\)题 ...

  7. Codeforces Round #699 (Div. 2) F - AB Tree(贪心、树上DP)超级清晰,良心题解,看不懂来打我 ~

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Codeforces Round #699 (Div. 2) F - AB Tree Problem ...

  8. Codeforces Round #507 (Div. 1) D. You Are Given a Tree 根号分治 + dp

    传送门 题意: 有一颗nnn个节点的树,其中一个简单路径集合被称为kkk合法当且仅当: 树的每个节点至多属于一条路径,且每条路径恰好包含kkk个点. 对于k∈[1,n]k\in [1,n]k∈[1,n ...

  9. Codeforces Round #453 (Div. 1) D. Weighting a Tree 构造 + dfs树

    传送门 文章目录 题意: 思路: 题意: 给你一颗nnn个点的图,每个点都有一个点权cic_ici​,要求你给每个边赋一个权值kik_iki​,要求对于每个点与他相连的边的权值之和等于这个点的点权ci ...

最新文章

  1. 新手探索NLP(六)——全文检索
  2. c语言定义可变长度的数组,有没有办法在c中创建一个可变长度数组全局?
  3. Android github 快速实现多人协作
  4. 帧中继(Frame Relay)实验
  5. MySQL中MVCC+行级锁的工作机制(源码佐证)
  6. tcpdump抓包最常用的命令
  7. 1,机器学习应用概述
  8. Django中的富文本编辑器的使用
  9. java class getfields_JAVA反射中的getFields()方法和getDeclaredFields ()方法的区别
  10. 基于机智云平台的微电网光伏模块数据采集装置的设计
  11. 使用python自动发送QQ消息
  12. 二元函数可导与可微的关系_如何理解多元函数可微与可偏导的关系?
  13. 【废了-准备删除01】渗透测试靶机搭建——基于WAMP的drupal7.x管理系统
  14. 浅谈ES6基础——Promise
  15. 做好自媒体需要具备的几个心态?!
  16. YV12toI420 yuv420、NV12、YV12相互转换
  17. 似然函数取对数的原因
  18. php公众号交友源码_个性定制微信导航源码,PHP公众号导航源码,含手机wap版,微信数据...
  19. 干货|ACCA F2经济订货批量(EOQ)
  20. 前端面试总结(持续更新中~~~~)

热门文章

  1. android img标签属性_微信小程序 组件叠加效果(如 Android 中的添加蒙层)
  2. java线程锁的作用,大厂面经合集
  3. [LeetCode]202. Happy Number(平衡二叉树 哈希表)
  4. 美国计算机专业录取率,美国留学高录取率院校计算机专业申请条件是什么? 爱问知识人...
  5. 箱形图适用于哪种数据_盘点 | 十分钟进阶Excel数据可视化
  6. java冒泡函数解释,JS DOM操作 函数 事件 阻止事件冒泡
  7. 网络推广策略之如何稳定新站的关键词排名?
  8. 产品网络推广方案之网站导航栏如何设置会更利于排名提升?
  9. 原创文章收录不高从根源找问题
  10. hashmap转红黑树的阈值为8_面试必问的HashMap,一次彻底帮你搞定HashMap源码