[JSOI2015]字符串树

link

很简单一道题,考场上脑残了。

很容易想到离线处理,又很容易想到可以拆分询问(树上路径询问要么用树链剖分拆成若干小段,要么用树上前缀拆成三段加减),又很容易想到可以用map和O2解决问题。

艹,考场上想的八九不离十了,结果脑子一抽用莫队加Trie来写,喜提0分。悲哀。

STL大法好啊!

#include<cstdio>
#include<algorithm>
#include<string>
#include<iostream>
#include<map>
#define zczc
using namespace std;
const int N=100010;
const int S=12;
inline void read(int &wh){
	wh=0;int f=1;char w=getchar();
	while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
	while(w>='0'&&w<='9'){wh=wh*10+w-'0';w=getchar();}
	wh*=f;return;
}
inline void swap(int &s1,int &s2){
	int s3=s1;s1=s2;s2=s3;return;
}

struct vv{int a[S],len;};

int m,n;
struct edge{int t,next;string v;}e[N<<1];
int head[N],esum;
void add(int fr,int to,string val){
	e[++esum]=(edge){to,head[fr],val};head[fr]=esum;
}

int tot,dfn[N],d[N],nxt[N][22];
void dfs(int wh,int fa,int deep){
	dfn[wh]=++tot;nxt[wh][0]=fa;d[wh]=deep+1;
	for(int i=1;i<=20;i++)nxt[wh][i]=nxt[nxt[wh][i-1]][i-1];
	for(int i=head[wh],th;i;i=e[i].next)
		if((th=e[i].t)^fa)dfs(th,wh,deep+1);
}
int lca(int s1,int s2){
	if(d[s1]<d[s2])swap(s1,s2);
	for(int i=20;i>=0;i--)
		if(d[nxt[s1][i]]>=d[s2])s1=nxt[s1][i];
	if(s1==s2)return s1;
	for(int i=20;i>=0;i--)
		if(nxt[s1][i]^nxt[s2][i])s1=nxt[s1][i],s2=nxt[s2][i];
	return nxt[s1][0];
}

struct node{
	int id,op,pl;string val;
}c[N<<2];int sr;
inline bool cmp(node s1,node s2){
	return dfn[s1.pl]<dfn[s2.pl];
}
int use=1,ans[N];map<string,int>mp;
void solve(int wh,int fa){
	while(use<=sr&&dfn[c[use].pl]<=dfn[wh]){
		ans[c[use].id]+=c[use].op*mp[c[use].val];
		use++;
	}
	for(int i=head[wh],th;i;i=e[i].next){
		if((th=e[i].t)==fa)continue;
		for(int j=0;j<=e[i].v.size();j++)mp[e[i].v.substr(0,j)]++;
		solve(th,wh);
		for(int j=0;j<=e[i].v.size();j++)mp[e[i].v.substr(0,j)]--;
	}
}

string val;

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	int s1,s2;read(m);
	for(int i=1;i<m;i++){
		read(s1);read(s2);cin>>val;add(s1,s2,val);add(s2,s1,val);
	}
	dfs(1,0,1);read(n);
	for(int i=1;i<=n;i++){
		read(s1);read(s2);cin>>val;
		c[++sr]=(node){i,1,s1,val};
		c[++sr]=(node){i,1,s2,val};
		c[++sr]=(node){i,-2,lca(s1,s2),val};
	}
	sort(c+1,c+sr+1,cmp);
	solve(1,0);
	for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
	
	return 0;
}
posted @ 2022-04-03 14:08  Feyn618  阅读(32)  评论(0编辑  收藏  举报