zoukankan      html  css  js  c++  java
  • CF570D Tree Requests

    洛咕

    题意:给定一个以1为根的n个节点的树,每个点上有一个字母((a-z)),每个点的深度定义为该节点到1号节点路径上的点数.每次询问 (a,b) 查询以(a)为根的子树内深度为(b)的节点上的字母重新排列之后是否能构成回文串.(n,m<=500000.)

    分析:还是那个模板,然后一个子树内的字母重新排列之后要能够构成回文串,当且仅当出现次数为奇数个的字母至多只有一个.根据这个性质,我们可以用二进制位来表示每个字母,即每个节点赋上权值(1<<(ch-'a')),然后合并的时候就把权值异或起来就好了.最后就只要计算这个数是否只有最多一位为1就好了.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=500005;
    int n,m,visit[N],ans[N];char s[N];
    int size[N],son[N],sum[N],val[N],dep[N];
    int tot,head[N],nxt[N],to[N];
    inline void add(int a,int b){
    	nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
    }
    struct node{int h,nxt;}a[N];int Head[N];
    inline void Add(int v,int h,int id){
        a[id]=(node){h,Head[v]};Head[v]=id;
    }
    inline void pre_dfs(int u){
    	size[u]=1;
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];dep[v]=dep[u]+1;
    		pre_dfs(v);size[u]+=size[v];
    		if(size[v]>size[son[u]])son[u]=v;
    	}
    }
    inline void update(int u){
    	sum[dep[u]]^=val[u];//异或和a
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];if(visit[v])continue;
    		update(v);
    	}
    }
    inline bool calc(int x){//计算这个数为1的位有多少个
    	int cnt=0;
    	for(int i=0;i<=25;++i)if(x&(1<<i))++cnt;
    	return cnt<=1;
    }
    inline void dfs(int u,int keep){
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];if(son[u]==v)continue;
    		dfs(v,0);
    	}
    	if(son[u])dfs(son[u],1),visit[son[u]]=1;update(u);
    	for(int i=Head[u];i;i=a[i].nxt)ans[i]=calc(sum[a[i].h]);
    	visit[son[u]]=0;if(!keep)update(u);
    }
    int main(){
    	n=read(),m=read();
    	for(int i=2;i<=n;++i){int x=read();add(x,i);}//直接建有向边
    	scanf("%s",s+1);for(int i=1;i<=n;++i)val[i]=1<<(s[i]-'a');//给节点赋权值
    	for(int i=1,v,h;i<=m;++i)v=read(),h=read(),Add(v,h,i);//把询问离线
    	dep[1]=1;//刚开始这里没赋值,调了两个小时
        pre_dfs(1);dfs(1,1);for(int i=1;i<=m;++i)puts(ans[i]?"Yes":"No");
        return 0;
    }
    
    
  • 相关阅读:
    HDU4474 Yet Another Multiple Problem BFS搜索
    HDU4473 Exam 数学分析
    2013ACM多校联合(4)
    POJ1273 网络流...
    HDU4472 Count 递推
    POJ1149 PIGS 网络流
    UVA10881 Piotr's Ants 想法题
    javascript js string.Format()收集
    修改 设置 vs.net 网站 调试 设为 起始页
    【转】HTML5杂谈 概念与现行游戏 割绳子 宝石迷阵
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11666796.html
Copyright © 2011-2022 走看看