loneliness - ShinriiTin's Blog - 博主是sb
codeforces 455E Function
kangaroo

loneliness

ShinriiTin posted @ 2015年6月17日 18:03 in 未分类 with tags 某不科学的三千元系列 , 777 阅读

题意:

给出一棵以1为根的有向树,每个节点上有一个字符(只会是小写字母)。

多次询问,给出一个字符集合,要求统计树上合法的串的数量。

合法的串满足4个要求:

1.是树上某个点向根方向的走所形成的串

2.串中所有的字符来自给定的字符集合

3.给定的字符集合中的每一个字符都在串中出现过

4.没有被任意一个满足前三条条件的路径完全包含

树的节点数和询问次数均不超过105

 

分析:

如果一个路径合法的串,当且仅当该路径向两端延伸1个位置都不能有在路径出现的字符。

我们记录每个节点向根方向的最近的出现某个字符的节点,显然合法的串只可能出现在这条路径上。

再记录每个节点所有儿子的字符集合,对于每个节点按深度枚举要走到的字符,判断是否合法。

 

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

#define g() getchar()
template<class Q>inline void Scan(Q&x){
	char c; while(c=g(),c<48||c>57);
	for(x=0;c>47&&c<58;c=g())x=10*x+c-48;
}

#define rep(i,a,b) for(int i=a;i<b;++i)

const int MAXN=50005;
const int Alpha=26;
typedef long long ll;

struct edge{
	int t,n;
	edge(int t=0,int n=0):t(t),n(n){}
}e[MAXN<<1];
int head[MAXN],tot;
inline void AddEdge(int s,int t){
	e[++tot]=edge(t,head[s]),head[s]=tot;
	e[++tot]=edge(s,head[t]),head[t]=tot;
}

char a[MAXN],b[MAXN];

int p[MAXN],dep[MAXN];

int last[MAXN][Alpha];

ll son[MAXN];

void dfs(int x){
	rep(i,0,Alpha)
		last[x][i]=last[p[x]][i];
	last[x][a[p[x]]-'a']=p[x];
	for(int i=head[x],y;i;i=e[i].n)
		if((y=e[i].t)!=p[x]){
			p[y]=x;
			dep[y]=dep[x]+1;
			son[x]|=1ll<<(a[y]-'a');
			dfs(y);
		}
}

int n,m;

int ans[MAXN];

const int SIZE=(1<<18)-1;
struct hash{
	ll set[MAXN];
	int next[MAXN],id[MAXN];
	int head[SIZE+1],tot;
	inline void insert(ll s,int Id){
		int p=s&SIZE;
		set[++tot]=s,next[tot]=head[p];
		id[tot]=Id,head[p]=tot;
	}
	inline void update(ll s){
		int p=s&SIZE;
		for(int i=head[p];i;i=next[i])
			if(set[i]==s)++ans[id[i]];
	}
}set;

inline bool cmp(int a,int b){return dep[a]>dep[b];}

inline void deal(int x){
	static int q[Alpha+1];
	rep(i,0,Alpha)q[i]=last[x][i];
	sort(q,q+Alpha,cmp);
	ll S=1ll<<(a[x]-'a');
	rep(i,0,Alpha){
		if(S&son[x])break;
		if(!q[i])break;
		ll s=1ll<<(a[q[i]]-'a');
		if(!(S&s)){
			set.update(S);
		}
		S|=s;
	}
	if(S&son[x])return;
	set.update(S);
}

int main(){
	freopen("loneliness.in","r",stdin);
	freopen("loneliness.out","w",stdout);
	Scan(n),Scan(m);
	scanf("%s",a+1);
	rep(i,1,n){
		int u,v;
		Scan(u),Scan(v);
		AddEdge(u,v);
	}
	rep(i,1,m+1){
		ll S=0;
		scanf("%s",b);
		int l=strlen(b);
		rep(j,0,l){
			S|=1ll<<(b[j]-'a');
		}
		set.insert(S,i);
	}
	dep[1]=1,dfs(1);
	rep(i,1,n+1)deal(i);
	rep(i,1,m+1)printf("%d\n",ans[i]);
	return 0;
}
Avatar_small
Emma 说:
2023年1月24日 01:08

This interesting problem presents a unique challenge in which the user must count the number of legal strings on a directed tree, given a character set. The buy real estate Okatie strings must meet four distinct requirements for them to be considered legal. This task requires the user to have a keen understanding of the tree structure, as well as the character set provided. It's a great mental exercise, and it can be quite rewarding!


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter