传送门

DFS重标号+二分

打比赛的时候想了很多方法..DFS序,BFS序,倍增什么的都考虑了一遍,但是几乎要么是可以维护两个区间但是代码复杂度爆炸,要么就是只能维护单一维度的信息。

这道题的具体做法就是先DFS遍历一遍,记一下每个点的出入栈时间。按照每个点的深度排序。这样就可以二分出深度,然后根据入栈的时间可以再在这个深度内二分出合适的区间。范围就是询问节点的出入栈时间。

//CF 570D
//by Cydiater
//2016.10.14
#include <iostream>
#include <cstdlib>
#include <queue>
#include <map>
#include <ctime>
#include <cmath>
#include <map>
#include <cstdio>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define up(i,j,n)		for(int i=j;i<=n;i++)
#define down(i,j,n)		for(int i=j;i>=n;i--)
const int MAXN=1e6+5;
const int oo=0x3f3f3f3f;
inline int read(){
	char ch=getchar();int x=0,f=1;
	while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
int LINK[MAXN],len=0,N,M,tim=0,pos[MAXN],Xor[MAXN],lef1,lef2,rig1,rig2;
char s[MAXN];
struct edge{
	int y,next;
}e[MAXN];
struct Node{
	int in,out,dep,id,v;
}a[MAXN];
namespace solution{
	inline void insert(int x,int y){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;}
	inline bool cmp(Node x,Node y){return x.dep==y.dep?x.in<y.in:x.dep<y.dep;}
	void dfs(int Node,int deep){
		a[Node].in=++tim;a[Node].dep=deep;a[Node].id=Node;
		for(int i=LINK[Node];i;i=e[i].next)dfs(e[i].y,deep+1);
		a[Node].out=++tim;
	}
	void init(){
		N=read();M=read();
		up(i,2,N){
			int Node=read();
			if(i==Node)continue;
			insert(Node,i);
		}
		scanf("%s",s+1);
		up(i,1,N)a[i].v=s[i]-'a';
		dfs(1,1);
		sort(a+1,a+N+1,cmp);
		up(i,1,N){
			pos[a[i].id]=i;
			Xor[i]=((1<<a[i].v)^Xor[i-1]);
		}
	}
	int get1(int lim){//<=
		int leftt=1,rightt=N,mid;
		while(leftt+1<rightt){
			mid=(leftt+rightt)>>1;
			if(a[mid].dep>=lim)	rightt=mid;
			else                leftt=mid;
		}
		if(a[leftt].dep>=lim)		return leftt;
		return rightt;
	}
	int get2(int lim){//>=
		int leftt=1,rightt=N,mid;
		while(leftt+1<rightt){
			mid=(leftt+rightt)>>1;
			if(a[mid].dep<=lim)	leftt=mid;
			else                rightt=mid;
		}
		if(a[rightt].dep<=lim)		return rightt;
		return leftt;
	}
	int get3(int lim){//<=
		int leftt=lef1,rightt=rig1,mid;
		while(leftt+1<rightt){
			mid=(leftt+rightt)>>1;
			if(a[mid].in>=lim)	rightt=mid;
			else                leftt=mid;
		}
		if(a[leftt].in>=lim)		return leftt;
		return rightt;
	}
	int get4(int lim){//>=
		int leftt=lef1,rightt=rig1,mid;
		while(leftt+1<rightt){
			mid=(leftt+rightt)>>1;
			if(a[mid].in<=lim)	leftt=mid;
			else                rightt=mid;
		}
		if(a[rightt].in<=lim)		return rightt;
		return leftt;
	}
	void slove(){
		while(M--){
			int Node=pos[read()],dep=read();
			if(a[Node].dep>=dep){puts("Yes");continue;}
			lef1=get1(dep);rig1=get2(dep);
			lef2=get3(a[Node].in+1);rig2=get4(a[Node].out-1);
			int S=Xor[rig2]^Xor[lef2-1];int flag=0;
			if(lef2>rig2){
				puts("Yes");
				continue;
			}
			up(i,0,25)if((S&(1<<i))==(1<<i)&&flag){
				puts("No");
				flag=-1;
				break;
			}else if((S&(1<<i))==(1<<i)) flag=1;
			if(flag!=-1)puts("Yes");
		}
	}
}
int main(){
	//freopen("input.in","r",stdin);
	using namespace solution;
	init();
	slove();
	return 0;
}

CF570D:Tree Requests的更多相关文章

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

  2. CF 570 D. Tree Requests

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

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

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

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

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

  5. codeforces 570 D. Tree Requests (dfs)

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

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

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

  7. 爬虫入门系列(三):用 requests 构建知乎 API

    爬虫入门系列目录: 爬虫入门系列(一):快速理解HTTP协议 爬虫入门系列(二):优雅的HTTP库requests 爬虫入门系列(三):用 requests 构建知乎 API 在爬虫系列文章 优雅的H ...

  8. centos7下报错: import requests ImportError: No module named requests

    在网上扒了一个python脚本,在centos7上执行的时候报错: import requestsImportError: No module named requests 原因是:requests是 ...

  9. 转: python requests的安装与简单运用

    requests是Python的一个HTTP客户端库,跟urllib,urllib2类似,那为什么要用requests而不用urllib2呢? 官方文档中是这样说明的: python的标准库urlli ...

随机推荐

  1. Vue学习笔记-2

    前言 本文非vue教程,仅为学习vue过程中的个人理解与笔记,有说的不正确的地方欢迎指正讨论 1.computed计算属性函数中不能使用vm变量 在计算属性的函数中,不能使用Vue构造函数返回的vm变 ...

  2. Dockerfile创建自定义Docker镜像以及CMD与ENTRYPOINT指令的比较

    1.概述 创建Docker镜像的方式有三种 docker commit命令:由容器生成镜像: Dockerfile文件+docker build命令: 从本地文件系统导入:OpenVZ的模板. 关于这 ...

  3. closure!

    总结一下闭包. 闭包的定义:当一个内部函数被其外部函数之外的变量所引用时,就形成了一个闭包. 一个最简单的闭包: function A(){ var count=0; return function( ...

  4. 记一次ASP.NET网站的入侵和如何避免被入侵

    ASP.NET网站入侵第二波(LeaRun.信息化快速开发框架 已被笔者拿下) 详细介绍请看第二波 首先我要申明的是不是什么语言写出来的程序就不安全,而是得看写代码的人如何去写这个程序 前些日子我去客 ...

  5. Windows Phone 8 下载文件进度

    后台代码: public partial class MainPage : PhoneApplicationPage { private long siz; private long speed; p ...

  6. XMl各种格式转换功能代码

    package com.cdv.test; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.File ...

  7. MVC认知路【点点滴滴支离破碎】【四】----捆绑和缩小(BundleConfig.RegisterBundles)

    原文链接:http://www.asp.net/mvc/overview/performance/bundling-and-minification 打开App_Start\BundleConfig. ...

  8. GO语言数组和切片实例详解

    本文实例讲述了GO语言数组和切片的用法.分享给大家供大家参考.具体分析如下: 一.数组 与其他大多数语言类似,Go语言的数组也是一个元素类型相同的定长的序列. (1)数组的创建. 数组有3种创建方式: ...

  9. directly receive json data from javascript in mvc

    if you send json data to mvc,how can you receive them and parse them more simply? you can do it like ...

  10. 现代软件工程 第七章 【MSF】练习与讨论

    7.7  移山开发方法——比TFS敏捷更精简 几个软件学院的学生来请教阿超,同学们自豪地说,我们要用全套TFS敏捷开发模式开发项目! 真的?阿超不敢相信. 同学: 对!我们要用全5个工作项类型 – 任 ...