CF570D——Tree Requests
来源:互联网 发布:阿里云主机和云服务器 编辑:程序博客网 时间:2024/06/06 00:53
1、题目大意:给你一棵树,每个点有一个字符,然后我们定义1的深度是1,然后1的儿子深度是2...
然后有一个询问,询问以i为根节点的子树,然后深度是k的那层的所有字符,可否组成一个回文串
2、分析:首先来考虑一下回文串的性质,有什么性质呢,就是里面出现次数为奇数次的点一定不会超过1个,
否则我们一定可以弄出回文串,对吧
那么我们离线处理这个东西,我们首先建立dfs序线段树,线段树里啥也别存,然后我们将询问的操作按k的大小排序
对于k相同的操作,我们在一起处理,k最多不会超过n,对吧,我们怎么处理呢,首先线段树里的空的,
线段树里的每一个节点都是一个存26个字符的出现次数的数组
我们把所有第k层的数的字符都扔进线段树,那么我做这些询问的时候,我可以找到一颗子树对应的区间,对吧
但是这个区间里只有第k层的数在这里面存着,那么我查询这个区间就相当于查询以i为根节点的子树,深度是k的那层
对吧,之后我们返回一个存26个字符的出现次数的数组。但是这样的时间复杂度是26nlogn的对吧,虽然可以卡过,
但是还是保险的好。。。我们怎么办呢,状压,我们利用异或的半加性质,我们可以把线段树的每一个节点改成状压的
仔细想一下。。
然后我们的复杂度退化到nlogn
然后有一个询问,询问以i为根节点的子树,然后深度是k的那层的所有字符,可否组成一个回文串
2、分析:首先来考虑一下回文串的性质,有什么性质呢,就是里面出现次数为奇数次的点一定不会超过1个,
否则我们一定可以弄出回文串,对吧
那么我们离线处理这个东西,我们首先建立dfs序线段树,线段树里啥也别存,然后我们将询问的操作按k的大小排序
对于k相同的操作,我们在一起处理,k最多不会超过n,对吧,我们怎么处理呢,首先线段树里的空的,
线段树里的每一个节点都是一个存26个字符的出现次数的数组
我们把所有第k层的数的字符都扔进线段树,那么我做这些询问的时候,我可以找到一颗子树对应的区间,对吧
但是这个区间里只有第k层的数在这里面存着,那么我查询这个区间就相当于查询以i为根节点的子树,深度是k的那层
对吧,之后我们返回一个存26个字符的出现次数的数组。但是这样的时间复杂度是26nlogn的对吧,虽然可以卡过,
但是还是保险的好。。。我们怎么办呢,状压,我们利用异或的半加性质,我们可以把线段树的每一个节点改成状压的
仔细想一下。。
然后我们的复杂度退化到nlogn
这样就可以完美的通过了,(最不习惯写离线的算法了
#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>using namespace std;int head[600000], ne[600000], v[600000];int first[600000], nx[600000];int le[600000], ri[600000], ll;char str[600000];int tot;int ans[600000];struct node{ int num, dep, id; bool operator < (const node& rhs) const{ return dep < rhs.dep; }};node a[600000];struct segment_tree{ int q[2500000]; int x, y; inline void add(int l, int r, int o){ if(l == r && l == x){ q[o] = y; return; } int mid = (l + r) / 2; if(x <= mid) add(l, mid, 2 * o); if(x > mid) add(mid + 1, r, 2 * o + 1); q[o] = q[2 * o] ^ q[2 * o + 1]; return; } inline int query(int l, int r, int o){ if(x <= l && r <= y){ return q[o]; } int mid = (l + r) / 2; int ret = 0; if(x <= mid) ret ^= query(l, mid, 2 * o); if(y > mid) ret ^= query(mid + 1, r, 2 * o + 1); return ret; }} wt;inline void dfs(int x, int h){ nx[x] = first[h]; first[h] = x; le[x] = ++ ll; for(int i = head[x]; i != -1; i = ne[i]){ dfs(v[i], h + 1); } ri[x] = ll; return;}int main(){ memset(head, -1, sizeof(head)); memset(first, -1, sizeof(first)); int n, m; scanf("%d%d", &n, &m); for(int i = 2; i <= n; i ++){ scanf("%d", &v[i]); ne[i] = head[v[i]]; head[v[i]] = i; v[i] = i; } dfs(1, 1); scanf("%s", str); for(int i = 1; i <= m; i ++){ scanf("%d%d", &a[i].num, &a[i].dep); a[i].id = i; } sort(a + 1, a + m + 1); int i = 1; for( ; i <= m; ){ int height = a[i].dep; for(int j = first[height]; j != -1; j = nx[j]){ wt.x = le[j]; wt.y = (1 << (str[j - 1] - 'a')); wt.add(1, n, 1); } for( ; i <= m && a[i].dep == height; i ++){ wt.x = le[a[i].num]; wt.y = ri[a[i].num]; int hh = wt.query(1, n, 1); int cnt = 0; for(int k = 0; k <= 25; k ++) if(((1 << k) & hh)){ cnt ++; } if(cnt > 1) ans[a[i].id] = 0; else ans[a[i].id] = 1; } for(int j = first[height]; j != -1; j = nx[j]){ wt.x = le[j]; wt.y = 0; wt.add(1, n, 1); } } for(int j = 1; j <= m; j ++){ if(ans[j] == 1) printf("Yes\n"); else printf("No\n"); } return 0;}
0 0
- CF570D——Tree Requests
- [CF570D]Tree Requests
- cf570D. Tree Requests(dsu on tree)
- Python——Requests
- python——requests
- Python——requests库
- Python——requests安装
- Codeforces 570 D. Tree Requests
- codeforces 570 D Tree Requests
- Codeforces 570D Tree Requests
- 【CF 570D】Tree Requests
- Codeforces Round #316 Tree Requests
- 【cf 570d】Tree Requests
- CodeForces570D - Tree Requests 【dfs序】
- codeforces 570D Tree Requests
- Codeforces 570D Tree Requests
- Python 爬虫——requests库
- 快速上手 — Requests 2.10.0 文档
- SDE连接,创建数据集,数据导入以及数据导出
- 增加模拟器
- 描述系统架构—部署图、组件图
- Git可视化工具SourceTree的使用
- el表达式取map对象
- CF570D——Tree Requests
- NYOJ 61 传纸条(一)
- 简历投递三大误区!你get了吗?
- NeHe's Opengl 06:纹理映射error LNK1120: 1 unresolved externals和error LNK2019: unresolved external的问题
- ...... 处有未经处理的异常: 0xC0000005: 读取位置 0xcccccccc 时发生访问冲突
- Java实现人民币大写代码
- AngularJS实现跨域请求
- java Map及Map.Entry详解
- 关于Android RenderScript 的详细说明和一些实用文档