Codeforces Round #316 (Div. 2) D. Tree Requests 树 离线在线 算法

D. Tree Requests

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

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 vihi.
Let‘s consider the vertices in the subtree vi located
at depthhi.
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.

Input

The first line contains two integers nm (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 vihi (1?≤?vi,?hi?≤?n)
— the vertex and the depth that appear in thei-th query.

Output

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).

Sample test(s)

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".

题意,给出一个树,要求一些询问,某个结点的子树中的第q层能否形成回文串。

1.状态压缩,由于,只有26个字符,所以用一个int存每个字符的奇偶数(只需要知道奇偶性,下面也只需要用奇偶性),压缩内存。

2.如何判定回文,只要a-z的字符最多有一个字符出现奇数次,就可以形成回文串。也就是(x&(-x)),去掉最后的一个1后,还是非0说明存在2个1以上,也就不能构成回文

方法一:先来说下离线的做法,先把所有的询问读入,按dfs搜索的顺序,每个询问在进入前先异或上这层的值,出这个结点时,再异或上这层的值,先前该层的值异或两次抵消了,所以就是这个结点下的子树的该层的值了。复杂度为o(n);

#define N 500005
#define M 100005
#define maxn 205
#define MOD 1000000000000000007
int n,m,tree[N],t,v,h,ans[N],pre[N];
char str[N];
bool vis[N];
vector<int> p[N];
vector<pii> q[N];
int DFS(int f,int depth){
    FI(q[f].size()){
        ans[q[f][i].first] ^= pre[q[f][i].second];
    }
    FI(p[f].size()){
        DFS(p[f][i],depth + 1);
    }
    pre[depth] ^= (1<<(str[f - 1] - 'a'));
    FI(q[f].size()){
        ans[q[f][i].first] ^= pre[q[f][i].second];
    }
    return 0;
}
int main()
{
     while(S2(n,m)!=EOF)
    {
        FI(n + 1){
           p[i].clear();
           q[i].clear();
           pre[i] = 0;
           ans[i] = 0;
        }
        FI(n-1){
            S(t);
            p[t].push_back(i+2);
        }
        SS(str);
        FI(m){
           S2(v,h);
           q[v].push_back(mp(i,h));
        }
        DFS(1,1);
        FI(m){
            if(ans[i] & (ans[i] - 1))
                printf("No\n");
            else
                printf("Yes\n");
        }
    }
    return 0;
}

方法二:在线做法。先把树形结构转化成线形结构,也就是进入的时候标记一下,出来的时候标记一下,就可以转化成为一个线形增大的值。每个结点,只会影响到它所在层的值,所以,先预处理出每个结点在它的层中形成的状态存起来。然后,由于是要求结点v的子树,所以只要求出在s[v] e[v]之间的值,用二分的方法,找出起始结点的位置,和离开结点的位置用结束时的状态异或开始的状态,就可以求出来这个结点子树的状态了。复杂度由于要二分查找,为o(n * log(n);但离线的做法,更加有意义。

#define N 500005
#define M 100005
#define maxn 205
#define MOD 1000000000000000007
int n,m,tree[N],t,v,h,ans,s[N],e[N],index;
char str[N];
bool vis[N];
vector<int> p[N];
vector<pii> dep[N];
int DFS(int f,int depth){
    s[f] = index++;
    FI(p[f].size()){
        DFS(p[f][i],depth + 1);
    }
    dep[depth].push_back(mp(index,dep[depth].back().second^(1<<(str[f - 1] - 'a'))));
    e[f] = index++;
    return 0;
}
int main()
{
     while(S2(n,m)!=EOF)
    {
        FI(n + 1){
           p[i].clear();
           dep[i].clear();
           dep[i].push_back(mp(0,0));
        }
        FI(n-1){
            S(t);
            p[t].push_back(i+2);
        }
        SS(str);
        index = 1;
        DFS(1,1);
        FI(m){
           S2(v,h);
           int l = lower_bound(dep[h].begin(),dep[h].end(),mp(s[v],-1)) - dep[h].begin() - 1;
           int r = lower_bound(dep[h].begin(),dep[h].end(),mp(e[v],-1)) - dep[h].begin() - 1;
           ans = dep[h][r].second ^ dep[h][l].second;
           if(ans & (ans - 1))
                printf("No\n");
            else
                printf("Yes\n");
        }
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-18 23:39:56

Codeforces Round #316 (Div. 2) D. Tree Requests 树 离线在线 算法的相关文章

Codeforces Round #316 (Div. 2) D Tree Requests

官方题解是离线询问,dfs树形转线性,然后二分找区间. 还有一种比较好的做法是直接dfs,将当前访问这个结点u相关的询问之前的状态存起来,然后访问完以后利用异或开关性,得到这颗子树上的答案. 代码是学习别人的http://blog.csdn.net/squee_spoon/article/details/47666667 当时做的时候想得是树形转线性,觉得dfs会暴栈,想用bfs,之前又没写过,于是愣了一个钟头. #include<bits/stdc++.h> using namespace

Codeforces Round #316 (Div. 2) D. Tree Requests(DFS+状态压缩)

题意:给定一棵树,n个节点.每一个节点处有一个字母,结点的深度定义为节点到根结点1的距离, 有m个询问(u.v),每次回答以结点u为根的子树的深度为v的那些节点处的字母是否能组成一个回文串,特别的,空串也是回文串. 思路:首先说明推断回文串的方法,仅仅要出现次数为奇数个字母个数不超过2.那么这些字母一定能够组成回文串. 接下来考虑将树转成线性结构. 利用dfs+时间戳将结点依照深度存入一个线性结构里,Depth[i]数组里存的是深度为i的全部结点, 那么对于询问有三种情况.一种是dep[u]>=

Codeforces Round #401 (Div. 2) E 贪心,线段树

Codeforces Round #401 (Div. 2) A 循环节 B 暴力排一下 C 标记出来,但10^5,特耿直地码了个O(n^2)的上去,最气的是在最后3分钟的时候被叉== D 从后往前贪心暴糙一下就好.比赛时一眼瞄出来了不敢写,搞不懂这样竟然不会超时.. E. Hanoi Factory 题意:n个环体,内径a[i],外径b[i],高h[i].当 a[i+1]<b[i]<=b[i+1] 时,第 i 个环体可以堆在第 i+1个环体上.求可以堆出的最高高度. tags:佩服那些大佬,

Codeforces Round #316 (Div. 2)

A - Elections 1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,num[105],a[105][105]; 4 int main() 5 { 6 scanf("%d%d",&n,&m); 7 for(int i=1;i<=m;i++) 8 { 9 int item=1; 10 for(int j=1;j<=n;j++) 11 { 12 scanf("%d&

Codeforces Round #603 (Div. 2) E. Editor 线段树

E. Editor The development of a text editor is a hard problem. You need to implement an extra module for brackets coloring in text. Your editor consists of a line with infinite length and cursor, which points to the current character. Please note that

Codeforces Round #540 (Div. 3) F1. Tree Cutting (Easy Version) 【DFS】

任意门:http://codeforces.com/contest/1118/problem/F1 F1. Tree Cutting (Easy Version) time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output You are given an undirected tree of nn vertices. Some vert

Codeforces Round #629 (Div. 3) E. Tree Queries(lca题)

https://codeforces.com/contest/1328/problem/E E. Tree Queries You are given a rooted tree consisting of nn vertices numbered from 11 to nn. The root of the tree is a vertex number 11. A tree is a connected undirected graph with n−1n−1 edges. You are

Codeforces Round #353 (Div. 2) D. Tree Construction (二分,stl_set)

题目链接:http://codeforces.com/problemset/problem/675/D 给你一个如题的二叉树,让你求出每个节点的父节点是多少. 用set来存储每个数,遍历到a[i]的时候查找比a[i]大的数的位置,然后插入,而父亲就是刚好比a[i]小的数或刚好大的数. 然后讨论是哪一个数. 比如给你3 1 2 ,如图 1的父亲是3 ,2的父亲是1. 那我其实只要找左边或右边出现最晚的数就行了,用pair的first表示a[i],second表示出现的顺序i. 1 #include

数据结构 - Codeforces Round #353 (Div. 2) D. Tree Construction

Tree Construction Problem's Link ---------------------------------------------------------------------------- Mean: 给定n个数,按照构造Binary Search Tree的方式来构造BST树,按顺序输出每一个非root结点的父节点的值. analyse: 构造BST树最坏情况下时间复杂度为O(n),肯定会超时. 注意到只需要输出结点的父节点的值,不需要真的构造BST树. 插到第i