CF570D Tree Requests
离线 + 树状数组
如果子树中的一个深度的所有点中有两个以上的字母出现了奇数次,那么这个询问的答案就是$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的更多相关文章
- 解题:CF570D Tree Requests
题面 DSU on tree确实很厉害,然后这变成了一道裸题(逃 还是稍微说一下流程吧,虽然我那个模板汇总里写过 DSU on tree可以以$O(n\log n)$的复杂度解决树上子树统计问题,它这 ...
- CF570D——Tree Requests
1.题目大意:给你一棵树,每个点有一个字符,然后我们定义1的深度是1,然后1的儿子深度是2... 然后有一个询问,询问以i为根节点的子树,然后深度是k的那层的所有字符,可否组成一个回文串 2.分析:首 ...
- 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 ...
- CF 570 D. Tree Requests
D. Tree Requests http://codeforces.com/problemset/problem/570/D 题意: 一个以1为根的树,每个点上有一个字母(a-z),每次询问一个子树 ...
- Codeforces 570D TREE REQUESTS dfs序+树状数组 异或
http://codeforces.com/problemset/problem/570/D Tree Requests time limit per test 2 seconds memory li ...
- Codeforces 570D - Tree Requests(树上启发式合并)
570D - Tree Requests 题意 给出一棵树,每个节点上有字母,查询 u k,问以 u 为根节点的子树下,深度为 k 的所有子节点上的字母经过任意排列是否能构成回文串. 分析 一个数组 ...
- codeforces 570 D. Tree Requests 树状数组+dfs搜索序
链接:http://codeforces.com/problemset/problem/570/D D. Tree Requests time limit per test 2 seconds mem ...
- codeforces 570 D. Tree Requests (dfs)
题目链接: 570 D. Tree Requests 题目描述: 给出一棵树,有n个节点,1号节点为根节点深度为1.每个节点都有一个字母代替,问以结点x为根的子树中高度为h的后代是否能够经过从新排序变 ...
- Codeforces 570D TREE REQUESTS dfs序+树状数组
链接 题解链接:点击打开链接 题意: 给定n个点的树.m个询问 以下n-1个数给出每一个点的父节点,1是root 每一个点有一个字母 以下n个小写字母给出每一个点的字母. 以下m行给出询问: 询问形如 ...
随机推荐
- Fast Arrangement (线段树,延迟标志)
个人心得:线段树的延迟标志确实是减少了很多时间,思想比较简单,但是实现得时候和建立延迟的时候比较麻烦. 按照我的一些理解,就是更新时找到完全覆盖的区间时,更新延迟标志,不再往下更新,但此时父节点啥的都 ...
- [原]zeromq框架测试报告
一.环境: 服务器:linux 4核 16G 虚拟机 1台 客户端:linux 4核 16G 2000台(模拟) 数据包大小:1036字节 二.参数设置: ulimit -n 65536 服务端处理线 ...
- selenium定位方式源码的存放位置
find_element方法源码存在位置 by定位方法
- 严谨的程序案例Api
文档 功能 同步推荐关系 接口方法 syncRelation 参数描述 OriginalUsername 查询的用户用户名 RecommandUsername 推荐人用户名 返回值 status 1成 ...
- MariaDB 脚本
研究MariaDB, 需要mock up一些假数据: 生成n个长度整型数的函数rand_num: CREATE DEFINER=`root`@`localhost` FUNCTION `rand_nu ...
- python学习(五) 条件、循环和其他语句
第五章 条件.循环和其他语句 5.1 print和import的更多信息 5.1.1 使用逗号输出 >>> print('age',43,45) // 可以用逗号隔开 ...
- JavaScript笔记——面向对象与原型
JavaScript也是一门面向对象的语言.面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.但是,JavaScript竟然没有class,因此它的面向对象也 ...
- cocoa 线程操作
在Cocoa 中创建线程使用NSThread类的detachNewThreadSelector: toTarget:withObject:方法 NSPort *port1 = [NSPort port ...
- 分数CSD编码
有符号数系统:有三重值(1, 0, -1) SD编码:12 = 16 - 4 = 10000_0000 - 100 = 1_0000_0(-1)00; = 16 - 9 + 5 = 1_0000_00 ...
- java成神之——网络编程基本操作
网络编程 获取ip UDP程序示例 TCP程序 结语 网络编程 获取ip InetAddress id = InetAddress.getLocalHost(); // InetAddress id ...