标签:codeforces
题意:
给定n个点的树,m个询问
1是root,下面给出2——n每个点的父节点,
每个点有一个字母
下面n个小写字母给出每个点的字母。
下面m行给出询问:
询问形如 (u, deep) 问u点的子树中,距离根的深度为deep的所有点的字母能否在任意排列后组成回文串,能输出Yes.不能输出No
根到根的deep = 1,以此类推。
思路:
dfs序,给点重新标号,dfs进入u点的时间戳记为l[u], 离开的时间戳记为r[u], 这样对于某个点u,他的子树节点对应区间都在区间 [l[u], r[u]]内。
把距离根深度相同的点都存到vector里 D[i] 表示深度为i的所有点,在dfs时可以顺便求出。
把询问按深度排序,query[i]表示所有深度为i的询问。
接下来按照深度一层层处理。
对于第i层,把所有处于第i层的节点都更新到26个树状数组上。
然后处理询问,直接查询树状数组上有多少种字母是奇数个的,显然奇数个字母的种数要<=1
处理完第i层,就把树状数组逆向操作,相当于清空树状数组
注意的一个地方就是 询问的深度是任意的,也就是说可能超过实际树的深度,也可能比当前点的深度小。所以需要初始化一下答案。
代码如下:
#include<cstdio> #include<cstring> #include<string> #include<iostream> #include<algorithm> #include<vector> using namespace std; typedef long long ll; typedef pair<int, int>pii; const int N = 5e5+10; int n, m; int l[N], r[N], top; char s[N]; vector<int> G[N], D[N]; vector<pii> Q[N]; bool ans[N]; struct node { int maxn, c[N]; void init(int n) { maxn = n; memset(c, 0, sizeof(c)); } inline int Lowbit(int x){return x&(-x);} void change(int u, int x) { while(u <= maxn) { c[u] += x; u += Lowbit(u); } } int sum(int x) { int ans = 0; for(int i = x; i >= 1; i -= Lowbit(i)) { ans += c[i]; } return ans; } int query(int l, int r) { return sum(r) ^ sum(l-1); } }t[26]; void dfs(int u, int fa, int dep) { D[dep].push_back(u); l[u] = ++top; for(vector<int>::iterator i = G[u].begin(); i != G[u].end(); i++) { if(*i != fa) { dfs(*i, u, dep+1); } } r[u] = top; } int main() { scanf("%d%d", &n, &m); fill(ans, ans + m + 10, 1); for (int i = 0; i < 26; i++) t[i].init(n); for(int i = 2, u; i <= n; i++) { scanf("%d", &u); G[u].push_back(i); } top = 0; dfs(1, 1, 1); scanf("%s", s+1); for(int i = 1, u, v; i <= m; i++) { scanf("%d%d", &u, &v); Q[v].push_back(pii(u, i)); } for(int i = 1; i <= n; i++) { if(D[i].size() == 0) break; for(vector<int>::iterator j = D[i].begin(); j != D[i].end(); j++) { t[s[*j] - 'a'].change(l[*j], 1); } for(int v = 0; v < Q[i].size(); v++) { pii p = Q[i][v]; int cnt = 0; for(int k = 0; k < 26; k ++) { if(t[k].query(l[p.first], r[p.first])) cnt += t[k].query(l[p.first], r[p.first]) & 1; } ans[p.second] = cnt <= 1; } for(vector<int>::iterator iter = D[i].begin(); iter != D[i].end(); iter++) { t[s[*iter] - 'a'].change(l[*iter], -1); } } for(int i = 1; i <= m; i++) { ans[i] ? puts("Yes") : puts("No"); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
Codeforces Round #316 (Div. 2) D Tree Requests
标签:codeforces
原文地址:http://blog.csdn.net/doris1104/article/details/47700565