离线 + 树状数组

如果子树中的一个深度的所有点中有两个以上的字母出现了奇数次,那么这个询问的答案就是$No$,其他的情况吧都是$Yes$。

由于只有$26$个字母,我们可以考虑暴力检验,把树映射到$dfs$序上然后看一看子树区间中每一个字母出现了多少次。

我先写了一个动态开点的线段树,然后$O(26 * (n + q)logn)$完美爆炸了。

然后我们发现一个深度的所有点是可以相互利用的,这样子只要堆所有的询问离线一下按照深度排个序就好了,开$26$个树状数组单点修改+ 区间求和就做完了。

感觉速度飞快。

时间复杂度$O(nlogn + 26 * qlogn)$。

Code:

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std; const int N = 5e5 + ;
const int M = ; int n, qn, tot = , head[N];
int dfsc = , dep[N], id[N], siz[N];
char let[N];
vector <int> vec[N]; struct Edge {
int to, nxt;
} e[N << ]; inline void add(int from, int to) {
e[++tot].to = to;
e[tot].nxt = head[from];
head[from] = tot;
} struct Querys {
int x, h, res, id; friend bool operator < (const Querys &u, const Querys &v) {
return u.h < v.h;
} } q[N]; inline void read(int &X) {
X = ; char ch = ; int op = ;
for(; ch > ''|| ch < ''; ch = getchar())
if(ch == '-') op = -;
for(; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} bool cmp(int x, int y) {
return dep[x] < dep[y];
} inline void chkMax(int &x, int y) {
if(y > x) x = y;
} void dfs(int x, int fat, int depth) {
dep[x] = depth, id[x] = ++dfsc, siz[x] = ;
for(int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if(y == fat) continue;
dfs(y, x, depth + );
siz[x] += siz[y];
}
} namespace Bit {
int s[M][N]; #define lowbit(p) (p & (-p)) inline void modify(int t, int p, int v) {
for(; p <= n; p += lowbit(p))
s[t][p] += v;
} inline int query(int t, int p) {
int res = ;
for(; p > ; p -= lowbit(p))
res += s[t][p];
return res;
} } using namespace Bit; int main() {
// freopen("Sample.txt", "r", stdin);
// freopen("my.out", "w", stdout); read(n), read(qn);
for(int fat, i = ; i <= n; i++) {
read(fat);
add(fat, i), add(i, fat);
}
dfs(, , ); int maxd = ;
for(int i = ; i <= n; i++) {
chkMax(maxd, dep[i]);
vec[dep[i]].push_back(i);
} scanf("%s", let + );
for(int i = ; i <= qn; i++) {
q[i].res = , q[i].id = i;
read(q[i].x), read(q[i].h);
} sort(q + , q + + qn);
for(int i = ; i <= qn; i++) {
int lst = i;
for(; q[i].h == q[lst].h; i++);
i--;
if(q[i].h > maxd) continue; int vecSiz = vec[q[i].h].size();
for(int j = ; j < vecSiz; j++) {
int pos = vec[q[i].h][j];
modify(let[pos] - 'a', id[pos], );
} for(int j = lst; j <= i; j++)
for(int c = ; c < ; c++) {
int tmp = query(c, id[q[j].x] + siz[q[j].x] - ) - query(c, id[q[j].x] - );
if(tmp & ) ++q[q[j].id].res;
} for(int j = ; j < vecSiz; j++) {
int pos = vec[q[i].h][j];
modify(let[pos] - 'a', id[pos], -);
}
} /* for(int i = 1; i <= qn; i++)
printf("%d ", q[i].res);
printf("\n"); */ for(int i = ; i <= qn; i++)
if(q[i].res <= ) puts("Yes");
else puts("No"); return ;
}

CF570D Tree Requests的更多相关文章

  1. 解题:CF570D Tree Requests

    题面 DSU on tree确实很厉害,然后这变成了一道裸题(逃 还是稍微说一下流程吧,虽然我那个模板汇总里写过 DSU on tree可以以$O(n\log n)$的复杂度解决树上子树统计问题,它这 ...

  2. CF570D——Tree Requests

    1.题目大意:给你一棵树,每个点有一个字符,然后我们定义1的深度是1,然后1的儿子深度是2... 然后有一个询问,询问以i为根节点的子树,然后深度是k的那层的所有字符,可否组成一个回文串 2.分析:首 ...

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

    D. Tree Requests time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  4. CF 570 D. Tree Requests

    D. Tree Requests http://codeforces.com/problemset/problem/570/D 题意: 一个以1为根的树,每个点上有一个字母(a-z),每次询问一个子树 ...

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

    http://codeforces.com/problemset/problem/570/D Tree Requests time limit per test 2 seconds memory li ...

  6. Codeforces 570D - Tree Requests(树上启发式合并)

    570D - Tree Requests 题意 给出一棵树,每个节点上有字母,查询 u k,问以 u 为根节点的子树下,深度为 k 的所有子节点上的字母经过任意排列是否能构成回文串. 分析 一个数组 ...

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

    链接:http://codeforces.com/problemset/problem/570/D D. Tree Requests time limit per test 2 seconds mem ...

  8. codeforces 570 D. Tree Requests (dfs)

    题目链接: 570 D. Tree Requests 题目描述: 给出一棵树,有n个节点,1号节点为根节点深度为1.每个节点都有一个字母代替,问以结点x为根的子树中高度为h的后代是否能够经过从新排序变 ...

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

    链接 题解链接:点击打开链接 题意: 给定n个点的树.m个询问 以下n-1个数给出每一个点的父节点,1是root 每一个点有一个字母 以下n个小写字母给出每一个点的字母. 以下m行给出询问: 询问形如 ...

随机推荐

  1. matlab数据流仿真和时间流仿真

    simulink 使用的动态系统仿真,仿真需要求状态方程和输出方程,关键是求状态方程,而状态方程的求解有多种算法,可变步长和定步长,所以仿真时对求解器的选择和步长的设置就比较重要. 所谓基於数据流的仿 ...

  2. test20181219 奇怪的函数

    题意 奇怪的函数 [问题描述] 使得x^x达到或超过n位数字的最小正整数x是多少? [文件输入] 输入一个正整数n(n<=2*10^9). [文件输出] 输出使得x^x达到n位数字的最小正整数x ...

  3. 阿里云ESC服务器安装tomcat后无法远程访问

    问题描述:服务器上面没有部署文件,安装了tomcat,在服务器本地能通过"localhost:8080"访问到tom猫页面 但是远程访问“外网ip+:8080”就访问不了 解决方案 ...

  4. web 模板引擎

    baiduTemplate:  http://baidufe.github.io/BaiduTemplate/ artTemplate: https://github.com/aui/artTempl ...

  5. ②HttpURLConnection通过Json参数方式提交Post请求

    之前的文章介绍过通过报文的方式HttpURLConnection提交post请求,今天介绍下通过Json参数的方法提交Post请求,先上代码 public static HttpResponse se ...

  6. 选择排序的JavaScript实现

    思想 原址比较的排序算法.即首先找到数结构中的最小值并将其放置在第一位,然后找到第二小的值将其放置在第二位...以此类推. 代码 function selectionSort(arr) { const ...

  7. oracle11g,安装失败,提示找不到文件,win7 64位下报错

    提示: 未找到文件 E:\app\Administrator\product\11.2.0\dbhome_5\owb\external\oc4j_applications\applications\W ...

  8. 微信H5支付 EasyWechat

    其中如果想在一个laravel中使用多个不同主题的支付账户,可以在方法实例对象时,将对应的参数进行修改配置. 其中小程序支付,已得到验证. 1.公众号支付等资格申请 2.公众号对应的支付商户主体申请 ...

  9. ODBC、OLEDB、ADO、SQL的关系

    对于一个刚接触数据库的菜鸟来说(比如我),总是搞不清SQL.ADO.OLE DB.ODBC,大脑中一片混乱,好像懂了,又好像没懂,非常的苦恼,今天下了点功夫研究了一下,贴出来,其中肯定有好多错误,希望 ...

  10. (转)Oracle执行字符串

    declare v_out ); begin execute immediate 'select p_guid from c_itcomp where rownum = 1 ' into v_out; ...