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;
    }
    
    
  • 相关阅读:
    HDU 5583 Kingdom of Black and White 水题
    HDU 5578 Friendship of Frog 水题
    Codeforces Round #190 (Div. 2) E. Ciel the Commander 点分治
    hdu 5594 ZYB's Prime 最大流
    hdu 5593 ZYB's Tree 树形dp
    hdu 5592 ZYB's Game 树状数组
    hdu 5591 ZYB's Game 博弈论
    HDU 5590 ZYB's Biology 水题
    cdoj 1256 昊昊爱运动 预处理/前缀和
    cdoj 1255 斓少摘苹果 贪心
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11666796.html
Copyright © 2011-2022 走看看