【思维题】 Codeforces 570D Tree Requests

通道

题意:一棵树,每个节点有一个点值(字符),问u子树的深度为k的所有节点组成的字符串是否为回文

思路:搜出dfs序及该节点的深度,那么u节点深度为K的那一段肯定在dfs序[l,r]区间内,然后对于回文的处理,要么这段异或和为0,要么lowbit(x)=x

代码:

#include <bits/stdc++.h>
using namespace std;

const int maxn = 500005;

typedef pair <int, int> PII;
vector <int> E[maxn];
vector <PII> H[maxn];

int dep[maxn], l[maxn], r[maxn], dfs_clock = 0;
char str[maxn];

void dfs(int x, int d) {
    dep[x] = d;
    l[x] = ++dfs_clock;
    for(int i : E[x]) {
        dfs(i, d + 1);
    }
    r[x] = dfs_clock;
}
int lowbit(int x) {
    return x & -x;
}
int main() {
    int n, m, x, y, v, h;
    scanf("%d%d", &n, &m);
    for(int i = 2; i <= n; i++) {
        scanf("%d", &x);
        E[x].push_back(i);
    }
    scanf("%s", str + 1);
    dfs(1, 1);
    for(int i = 1; i <= n; i++) H[i].push_back(make_pair(0, 0));
    for(int i = 1; i <= n; i++) {
        H[dep[i]].push_back(make_pair(l[i], 1 << (str[i] - ‘a‘)));
    }
    for(int i = 1; i <= n; i++) {
        sort(H[i].begin(), H[i].end());
        for(int j = 1; j < H[i].size(); j++) H[i][j].second ^= H[i][j - 1].second;
    }
    while(m--) {
        scanf("%d%d", &v, &h);
        int R = upper_bound(H[h].begin(), H[h].end(), make_pair(r[v], 1 << 30)) - H[h].begin();
        int L = upper_bound(H[h].begin(), H[h].end(), make_pair(l[v], 0)) - H[h].begin();
        int X = H[h][R - 1].second ^ H[h][L - 1].second;
        if((R - L) & 1) {
            printf("%s\n", lowbit(X) == X ? "Yes" : "No");
        } else {
            printf("%s\n", X == 0 ? "Yes" : "No");
        }
    }
    return 0;
}

时间: 2024-10-07 12:58:56

【思维题】 Codeforces 570D Tree Requests的相关文章

Codeforces 570D TREE REQUESTS dfs序+树状数组 异或

http://codeforces.com/problemset/problem/570/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

Codeforces 570D Tree Requests(Dsu On the Tree)

题目链接 Tree Requests 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define rep(i, a, b) for (int i(a); i <= (b); ++i) 6 7 typedef long long LL; 8 9 const int N = 500010; 10 const int A = 31; 11 12 int cntf[N], sz[N], h[N]; 13 vector <i

Codeforces 570D TREE REQUESTS dfs序+树状数组

链接 题解链接:点击打开链接 题意: 给定n个点的树,m个询问 下面n-1个数给出每个点的父节点,1是root 每个点有一个字母 下面n个小写字母给出每个点的字母. 下面m行给出询问: 询问形如 (u, deep) 问u点的子树中,距离根的深度为deep的所有点的字母能否在任意排列后组成回文串,能输出Yes. 思路:dfs序,给点重新标号,dfs进入u点的时间戳记为l[u], 离开的时间戳记为r[u], 这样对于某个点u,他的子树节点对应区间都在区间 [l[u], r[u]]内. 把距离根深度相

codeforces 570D.Tree Requests

[题目大意]: 给定一棵树,树的每个节点对应一个小写字母字符,有m个询问,每次询问以vi为根节点的子树中,深度为hi的所有节点对应的字符能否组成一个回文串: [题目分析]: 先画个图,可看出每次询问的所有节点都是一个从1开始bfs遍历完成的节点序列中的一段,已知深度hi的情况下,可以二分得到深度为hi的那一段的位置: 那么如何满足找到的节点必须在以vi为根的子树内这个条件? 可以想到dfs的时间戳,把1-n的数组按深度排序,深度相同的按照dfs时间戳排序: 这样就可以二分得到要求的所有节点的位置

贪心/思维题 Codeforces Round #310 (Div. 2) C. Case of Matryoshkas

题目传送门 1 /* 2 题意:套娃娃,可以套一个单独的娃娃,或者把最后面的娃娃取出,最后使得0-1-2-...-(n-1),问最少要几步 3 贪心/思维题:娃娃的状态:取出+套上(2),套上(1), 已套上(0),先从1开始找到已经套好的娃娃层数, 4 其他是2次操作,还要减去k-1个娃娃是只要套上就可以 5 详细解释:http://blog.csdn.net/firstlucker/article/details/46671251 6 */ 7 #include <cstdio> 8 #i

codeforces 570 D. Tree Requests 树状数组+dfs搜索序

链接:http://codeforces.com/problemset/problem/570/D 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 low

codeforces 848B Rooter&#39;s Song 思维题

http://codeforces.com/problemset/problem/848/B 给定一个二维坐标系,点从横轴或纵轴垂直于发射的坐标轴射入(0,0)-(w,h)的矩形空间.给出点发射的坐标轴,位置,延迟时间,发生碰撞则交换方向.求最后每个点的射出位置. 首先我们观察能得出两个结论,1. 类似蚂蚁爬树枝的问题,相遇只会交换方向,所以最后的射出点集只会因为碰撞而改变动点与射出点的对应关系,而不会增加减少射出点集.2.我们根据其射入位置和延迟时间可以计算出一个值v=pos-time,只有这

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

codeforces 570 D. Tree Requests (dfs)

题目链接: 570 D. Tree Requests 题目描述: 给出一棵树,有n个节点,1号节点为根节点深度为1.每个节点都有一个字母代替,问以结点x为根的子树中高度为h的后代是否能够经过从新排序变成一个回文串? 解题思路: 判断是不是回文串,可以统计集合中出现过的字母的个数,出现奇数次的字母个数小于1,即为回文串,否则不是.所以我们可以使用状压统计当前区间中字母出现的奇偶次数. 对于如何快速的求出区间,先dfs整棵树,标记下来每个节点进栈的时间和出栈的时间,然后把高度一样的点按照进栈时间顺序