版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35649707/article/details/82867060
Last chance
可以连两个的肯定可以增广,剩下的线段树优化见图跑网络流。
输出方案可以dfs反向边来退流。
#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=2e5+50, INF=0x3f3f3f3f;
int n,m,tot,bg,id[N],vis[N];
vector <pii> vec;
namespace mcmf {
int g[N],nt[N],vt[N],c[N],ec=1;
int cur[N],lev[N],que[N],hd,tl,src,des;
int flow;
inline void add(int x,int y,int cc) {
nt[++ec]=g[x]; g[x]=ec; vt[ec]=y; c[ec]=cc;
nt[++ec]=g[y]; g[y]=ec; vt[ec]=x; c[ec]=0;
}
inline bool bfs() {
for(int i=1;i<=des;i++) lev[i]=0;
lev[que[hd=tl=1]=src]=1;
while(hd<=tl) {
int u=que[hd++];
for(int e=g[u];e;e=nt[e]) {
if(!c[e] || lev[vt[e]]) continue;
lev[vt[e]]=lev[u]+1; que[++tl]=vt[e];
if(vt[e]==des) return true;
}
} return false;
}
inline int dinic(int x,int f) {
if(x==des) return f;
int rs=0;
for(int &e=cur[x];e;e=nt[e]) {
if(!c[e] || (lev[vt[e]]!=lev[x]+1)) continue;
int o=dinic(vt[e],min(f-rs,c[e]));
c[e]-=o; c[e^1]+=o; rs+=o;
if(rs==f) return rs;
} return lev[x]=0, rs;
}
inline void maxflow() {
int t;
while(bfs()) {
memcpy(cur+1,g+1,sizeof(int)*des);
while((t=dinic(src,INF))) flow+=t, memcpy(cur+1,g+1,sizeof(int)*des);
}
}
}
using namespace mcmf;
inline void build(int k,int l,int r) {
id[k]=++tot;
if(l==r) {mcmf::add(id[k],l,1); return;}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
add(id[k],id[k<<1],INF);
add(id[k],id[k<<1|1],INF);
}
inline void inc(int k,int l,int r,int L,int R) {
if(L<=l && r<=R) {add(tot,id[k],1); return;}
int mid=(l+r)>>1;
if(R<=mid) inc(k<<1,l,mid,L,R);
else if(L>mid) inc(k<<1|1,mid+1,r,L,R);
else inc(k<<1,l,mid,L,R), inc(k<<1|1,mid+1,r,L,R);
}
map <int,int> edge[N];
int tar;
inline void source(int x) {
if(x>=bg) {tar=x-bg+1; return;}
map <int,int> :: iterator it=edge[x].begin();
source(it->first); --it->second;
if(!it->second) edge[x].erase(it);
}
int main() {
n=rd(), m=rd(); tot=m;
mcmf::src=++tot;
build(1,1,m);
bg=tot+1;
for(int i=1;i<=n;i++) {
int type=rd(); ++tot;
if(!type) {
int k=rd();
while(k--) add(tot,rd(),1);
add(mcmf::src,tot,1);
} else if(type==1) {
int l=rd(), r=rd();
inc(1,1,m,l,r);
add(mcmf::src,tot,1);
} else {
int a=rd(), b=rd(), c=rd();
vis[a]=vis[b]=1; flow+=2;
add(tot,a,0); mcmf::c[ec]=1;
add(tot,b,0); mcmf::c[ec]=1;
add(tot,c,1);
}
}
des=++tot;
for(int i=1;i<=m;i++) if(!vis[i]) add(i,mcmf::des,1);
maxflow();
cout<<flow<<'\n';
for(int i=1;i<=tot;i++)
for(int j=g[i];j;j=nt[j])
if((j&1) && c[j]) edge[i][vt[j]]=c[j];
for(int i=1;i<=m;i++) {
int tag=1;
for(int e=g[i];e && tag;e=nt[e]) if(vt[e]==des && c[e]) tag=0;
if(tag) source(i), printf("%d %d\n",tar,i);
}
}
Space Isaac
一个数 不能被凑出来,那么 必须在 集合中,也就是集合中的数可以两两配对。
从小到大排序后,因为相邻两个数的距离和配对的数的距离,用哈希判断是否所有距离相同。
#include <bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
typedef unsigned long long ULL;
const ULL base=998244353;
const int mod=1e9+7;
const int N=2e5+50;
ULL pw[N], pre[N], suf[N];
int n,a[N],M;
unordered_map <int,int> mp;
int main() {
n=rd(), M=rd();
for(int i=1;i<=n;i++) a[i]=rd();
sort(a+1,a+n+1);
for(int i=1;i<=n;i++) mp[a[i]]=i;
pw[0]=1;
for(int i=1;i<=n;i++) pw[i]=pw[i-1]*base;
for(int i=2;i<=n;i++) pre[i]=pre[i-1]*base+a[i]-a[i-1];
for(int i=n-1;i>=1;i--) suf[i]=suf[i+1]+pw[n-i-1]*(a[i+1]-a[i]);
vector <int> vec;
ULL hv(0);
for(int i=2;i<=n;i++) hv=hv+pw[i-2]*(a[i]-a[i-1]);
for(int i=1;i<=n;i++) {
ULL tar;
if(i!=n) tar=suf[i+1]*pw[i]+(a[1]-a[n]+M)*pw[i-1]+pre[i];
else tar=suf[1];
if(hv==tar) vec.push_back((a[1]+a[i])%M);
}
sort(vec.begin(),vec.end());
printf("%d\n",vec.size());
for(int i=0;i<vec.size();++i) printf("%d ",vec[i]);
}
Hyperspace Highways
建圆方树。
#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
inline void W(int x) {
static int buf[50];
if(!x) {putchar('0'); return;}
if(x<0) {putchar('-'); x=-x;}
while(x) {buf[++buf[0]]=x%10; x/=10;}
while(buf[0]) {putchar(buf[buf[0]--]+'0');}
}
const int N=3e5+50, L=21;
int n,m,q,tot;
int dfn[N],low[N],vis[N],vs,ind;
int dep[N],fa[N][L];
stack <pii> e;
vector <int> g1[N];
vector <int> g2[N];
inline void dfs(int x,int f) {
low[x]=dfn[x]=++ind;
for(auto v:g1[x]) {
int top=e.size();
if(!dfn[v]) {
dfs(v,x), low[x]=min(low[x],low[v]);
e.push(pii(x,v));
if(dfn[x]<=low[v]) {
++vs; vector <int> vec;
while(e.size()>top) {
int u=e.top().first, v=e.top().second; e.pop();
if(vis[u]!=vs) vis[u]=vs, vec.push_back(u);
if(vis[v]!=vs) vis[v]=vs, vec.push_back(v);
}
++tot;
for(auto j:vec) g2[tot].push_back(j), g2[j].push_back(tot);
}
} else if(v!=f) low[x]=min(low[x],dfn[v]);
}
}
inline void dfs2(int x,int f) {
fa[x][0]=f; dep[x]=dep[f]+1;
for(int j=1;j<L;j++) fa[x][j]=fa[fa[x][j-1]][j-1];
for(auto v:g2[x]) if(v!=f) dfs2(v,x);
}
inline int lca(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
int d=dep[x]-dep[y];
for(int i=0;i<L;i++) if((d>>i)&1) x=fa[x][i];
if(x==y) return x;
for(int i=L-1;~i;i--) if(fa[x][i]^fa[y][i]) x=fa[x][i], y=fa[y][i];
return fa[x][0];
}
int main() {
n=rd(), m=rd(), q=rd(), tot=n;
for(int i=1;i<=m;i++) {
int x=rd(), y=rd();
g1[x].push_back(y);
g1[y].push_back(x);
} dfs(1,0); dfs2(1,0);
while(q--) {
int x=rd(), y=rd();
W((dep[x]+dep[y]-2*dep[lca(x,y)])/2), putchar('\n');
}
}
Interstellar battle
一个点有贡献,那么父亲消失而且自己不消失。
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+50;
int n,q,fa[N];
vector <int> g[N];
double p[N],s[N],ans;
inline void dfs(int x,int f) {
ans+=p[f]*(1-p[x]);
for(auto v:g[x]) if(v!=f) fa[v]=x, s[x]+=(1-p[v]), dfs(v,x);
}
int main() {
scanf("%d",&n); p[0]=1;
for(int i=1;i<=n;i++) scanf("%lf",&p[i]);
for(int i=1;i<n;i++) {
int x,y; scanf("%d%d",&x,&y);
++x; ++y;
g[x].push_back(y);
g[y].push_back(x);
}
dfs(1,0);
scanf("%d",&q);
for(int i=1;i<=q;i++) {
int x; double t;
scanf("%d%lf",&x,&t); ++x;
ans-=p[x]*s[x];
ans-=p[fa[x]]*(1-p[x]);
ans+=t*s[x];
ans+=p[fa[x]]*(1-t);
s[fa[x]]-=(1-p[x]);
s[fa[x]]+=(1-t);
p[x]=t;
printf("%.5f\n",ans);
}
}
Ancient civilizations
先做凸包,如果凸包上颜色大于两段,则无解。
否则可以规约为三角形中两个端点颜色相同的问题,然后找到三角形内部的一个点继续划分即可。
#include <bits/stdc++.h>
using namespace std;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=1e3+50;
int n,m,vis[N];
struct P {
int x,y,col,id;
P(int x=0,int y=0,int col=0,int id=0) : x(x),y(y),col(col),id(id) {}
friend inline P operator -(const P &a,const P &b) {return P(a.x-b.x,a.y-b.y);}
friend inline int operator *(const P &a,const P &b) {return a.x*b.y-a.y*b.x;}
} p[N],q[N];
typedef vector <P> vp;
typedef pair <int,int> pii;
vector <pii> ans;
inline void add(int x,int y) {ans.push_back(pii(x,y));}
inline bool in(P a,P b,P c,P d) {return (a-d)*(b-d)>0 && (b-d)*(c-d)>0 && (c-d)*(a-d)>0;}
inline void solve(P a,P b,P c) {
for(int i=1;i<=n;i++) if(in(a,b,c,p[i]) && p[i].col!=a.col) {
add(p[i].id,c.id);
solve(c,p[i],b);
solve(a,b,p[i]);
solve(p[i],c,a);
return;
}
vp vec;
for(int i=1;i<=n;i++) if(in(a,b,c,p[i])) add(a.id,p[i].id);
}
int main() {
n=rd();
for(int i=1;i<=n;i++) p[i].x=rd(), p[i].y=rd(), p[i].col=rd(), p[i].id=i;
if(n==2) {
if(p[1].col^p[2].col) puts("1\n1 2");
else puts("0");
return 0;
}
sort(p+1,p+n+1,[&] (const P &a,const P &b) {return a.x<b.x || (a.x==b.x && a.y<b.y);});
sort(p+2,p+n+1,[&] (const P &a,const P &b) {return (a-p[1])*(b-p[1])>0;});
q[m=1]=p[1];
for(int i=2;i<=n;i++) {
while(m>=2 && (p[i]-q[m-1])*(q[m]-q[m-1])>0) --m;
q[++m]=p[i];
}
int fir[2]={0,0}, lst[2]={0,0}, cnt=0;
for(int i=1;i<=m;i++) {
if(q[i].col!=q[i%m+1].col) {
++cnt;
if(cnt>2) {puts("Impossible"); return 0;}
if(!fir[0]) {
fir[0]=i, fir[1]=i%m+1;
if(q[i].col!=q[(i==1) ? m : (i-1)].col) lst[1]=i, lst[0]=i%m+1;
} else lst[1]=i, lst[0]=i%m+1;
}
}
for(int i=1;i<=m;i++) vis[q[i].id]=1;
if(!cnt) {
int tag=0;
for(int i=1;i<=n;i++) if(!vis[i] && p[i].col!=q[1].col) {
for(int j=1;j<=m;j++) {
if(j!=m) add(q[j].id,q[j+1].id);
solve(q[j],q[j%m+1],p[i]);
}
tag=1; break;
}
if(!tag) for(int i=1;i<n;i++) add(p[i].id,p[n].id);
} else {
for(int i=fir[1];i!=lst[1];i=i%m+1) {
add(q[i].id,q[i%m+1].id);
solve(q[i],q[i%m+1],q[lst[0]]);
}
for(int i=lst[0];i!=fir[0];i=i%m+1) {
add(q[i].id,q[i%m+1].id);
solve(q[i],q[i%m+1],q[fir[1]]);
}
}
cout<<ans.size()<<'\n';
for(int i=0;i<ans.size();i++) cout<<ans[i].first-1<<' '<<ans[i].second-1<<'\n';
}
Shady Lady
题解太长了专门写了一篇:传送门
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=2e5+50;
int n,m,vis[N];
struct P {
LL x,y; int id;
P(LL x=0,LL y=0,int id=0) : x(x),y(y),id(id) {}
friend inline P operator -(const P &a,const P &b) {return P(a.x-b.x,a.y-b.y);}
friend inline LL operator *(const P &a,const P &b) {return a.x*b.y-a.y*b.x;}
inline LL norm() {return x*x+y*y;}
} p[N],q[N];
inline void build_conv(int nn) {
m=1;
sort(q+1,q+nn+1,[&] (const P &a,const P &b) {return (a.x<b.x) || (a.x==b.x && a.y<b.y) || (a.x==b.x && a.y==b.y && a.id<b.id);});
sort(q+2,q+nn+1,[&] (const P &a,const P &b) {
LL det=(a-q[1])*(b-q[1]);
if(det!=0) return det>0;
return (a-q[1]).norm()<(b-q[1]).norm();
});
for(int i=2;i<=nn;i++) {
while(m>=2 && (q[i]-q[m-1])*(q[m]-q[m-1])>=0) --m;
q[++m]=q[i];
}
for(int i=1;i<=m;i++) if(q[i].x&1 || q[i].y&1) {puts("Ani"); exit(0);}
}
int main() {
n=rd()+1; p[1].id=1;
for(int i=2;i<=n;i++) p[i].x=rd(), p[i].y=rd(), p[i].id=i;
memcpy(q+1,p+1,sizeof(P)*(n));
build_conv(n);
for(int i=2;i<=m;i+=2) vis[q[i].id]=1, vis[q[i+1].id]=2;
m=0;
for(int i=1;i<=n;i++) if(vis[i]!=2) q[++m]=p[i];
build_conv(m);
m=0;
for(int i=1;i<=n;i++) if(vis[i]!=1) q[++m]=p[i];
build_conv(m);
puts("Borna");
}
AI robots
暴力枚举 的那一维,然后按照 从小到大枚举,用树状数组维护。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=5e5+50;
int n,K; LL ans;
vector <int> cd;
vector <int> ck;
vector <int> pos[N];
inline int id(vector <int> &vec,int t) {return lower_bound(vec.begin(),vec.end(),t)-vec.begin();}
struct data {
int x,r,k;
friend inline bool operator <(const data &a,const data &b) {return a.r<b.r;}
} a[N];
struct fenwick_tree {
vector <int> all,bit;
inline void init() {
sort(all.begin(),all.end());
all.erase(unique(all.begin(),all.end()),all.end());
bit.resize(all.size()+1);
}
inline void inc(int x,int v) {
int p=lower_bound(all.begin(),all.end(),x)-all.begin()+1;
for(;p<=all.size();p+=p&(-p)) bit[p]+=v;
}
inline int ask(int x,int rs=0) {
int p=upper_bound(all.begin(),all.end(),x)-all.begin();
for(;p;p-=p&(-p)) rs+=bit[p];
return rs;
}
} bit[N];
inline void inc_seg(int l,int r,int k) {
k=id(ck,k);
bit[k].inc(l,1);
bit[k].inc(r+1,-1);
}
inline int ask_point(int x,int l,int r) {
l=lower_bound(ck.begin(),ck.end(),l)-ck.begin();
r=upper_bound(ck.begin(),ck.end(),r)-ck.begin()-1;
int cnt=0;
for(int i=l;i<=r;i++) cnt+=bit[i].ask(x);
return cnt;
}
int main() {
n=rd(), K=rd();
for(int i=1;i<=n;i++) {
a[i].x=rd(), a[i].r=rd(), a[i].k=rd();
cd.push_back(a[i].x);
ck.push_back(a[i].k);
}
sort(cd.begin(),cd.end());
sort(ck.begin(),ck.end());
cd.erase(unique(cd.begin(),cd.end()),cd.end());
ck.erase(unique(ck.begin(),ck.end()),ck.end());
for(int i=1;i<=n;i++) {
int p=id(ck,a[i].k);
bit[p].all.push_back(a[i].x-a[i].r);
bit[p].all.push_back(a[i].x+a[i].r+1);
}
for(int i=0;i<ck.size();++i) bit[i].init();
sort(a+1,a+n+1);
for(int i=1;i<=n;i++) {
ans+=ask_point(a[i].x,a[i].k-K,a[i].k+K);
inc_seg(a[i].x-a[i].r,a[i].x+a[i].r,a[i].k);
}
cout<<ans<<'\n';
}
Self-exploration
相当于告诉了你
各自的段数和个数。
对于每个固定的前缀算一下贡献,后面是个球盒问题。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1e5+50, mod=1e9+7;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);}
inline int mul(int x,int y) {return (LL)x*y%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}
struct Combin {
int fac[N],ifac[N];
Combin() {
fac[0]=1;
for(int i=1;i<N;i++) fac[i]=mul(fac[i-1],i);
ifac[N-1]=power(fac[N-1],mod-2);
for(int i=N-2;~i;i--) ifac[i]=mul(ifac[i+1],i+1);
}
inline int C(int a,int b) {return mul(fac[a],mul(ifac[b],ifac[a-b]));}
inline int calc(int a,int b) {
if(a<b) return 0;
if(b==0) return a==0;
return C(a-1,b-1);
}
} C;
int n,c[2][2];
char A[N],B[N];
int a[N],lim;
inline int solve(char *lim) {
int len=strlen(lim+1);
if(len<n || ((c[0][1]+1!=c[1][0] && c[0][1]!=c[1][0]))) return 0;
if(len>n) return mul(C.calc(c[1][1]+c[0][1]+1,c[0][1]+1),C.calc(c[0][0]+c[1][0],c[1][0]));
for(int i=1;i<=n;i++) a[i]=lim[i]-'0';
int c0=0,c1=0,d0=0,d1=0,ans=0;
for(int i=1;i<=n;i++) {
if(a[i]^a[i-1]) (a[i]==1) ? ++d1 : ++d0;
(a[i]==1) ? ++c1 : ++c0;
if(d1>c[0][1]+1 || d0>c[1][0] || c1>c[1][1]+c[0][1]+1 || c0>c[0][0]+c[1][0]) break;
if(a[i+1]==1) {
int res0=c[0][0]+c[1][0]-c0-1, res1=c[1][1]+c[0][1]+1-c1;
int resd0=c[1][0]-d0-(a[i]!=0), resd1=c[0][1]+1-d1;
if(resd1!=resd0 && resd1!=resd0+1) continue;
ans=add(ans,mul(C.calc(res1,resd1),C.calc(res0+1,resd0+1)));
} else if(i==n) {
if(c0==c[0][0]+c[1][0] && c1==c[1][1]+c[0][1]+1 && d0==c[1][0] && d1==c[0][1]+1) ++ans;
}
}
return ans;
}
int main() {
scanf("%s%s",A+1,B+1);
for(int i=0;i<=1;i++) for(int j=0;j<=1;j++) cin>>c[i][j], n+=c[i][j];
++n;
int ans=dec(solve(B),solve(A));
int len=strlen(A+1);
for(int i=2;i<=len;i++)
c[A[i-1]-'0'][A[i]-'0']--;
ans=add(ans,(!c[0][0] && !c[1][0] && !c[0][1] && !c[1][1]));
cout<<ans<<'\n';
}
Palindrome Pairs
回文条件是加起来至多字母为奇数, 枚举是哪个字母就行了。
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+50;
int n,sta[N]; char ch[N];
map <int,int> mp;
long long ans=0;
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
int len=(scanf("%s",ch+1),strlen(ch+1));
for(int j=1;j<=len;j++) sta[i]^=1<<((ch[j]-'a'));
ans+=mp[sta[i]];
for(int j=0;j<26;j++) ans+=mp[sta[i]^(1<<j)];
mp[sta[i]]++;
} cout<<ans<<'\n';
}
Moonwalk challenge
端点处暴力枚举,其他哈希前缀和。
#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;
typedef unsigned long long ULL;
#define data Data
inline void W(int x) {
static int buf[50];
if(!x) {putchar('0'); return;}
if(x<0) {putchar('-'); x=-x;}
while(x) {buf[++buf[0]]=x%10; x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+'0');
}
const int N=2e5+50, L=21;
const ULL base=31;
int n,m,ans[N];
int fa[N][L],f2[N],val[N],dep[N];
ULL pw[N],ipw[N],upv[N];
vector <pii> edge[N];
struct data {
ULL vv;
int id,base,l;
data(ULL vv,int id,int base,int l) : vv(vv), id(id), base(base), l(l) {}
friend inline bool operator <(const data &a,const data &b) {return a.l>b.l;}
};
vector <data> qry[N];
inline void dfs_pre(int x,int f) {
fa[x][0]=f; dep[x]=dep[f]+1; f2[x]=x;
for(int i=1;i<L;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
for(auto v:edge[x]) if(v.first^f) {
val[v.first]=v.second;
upv[v.first]=upv[x]*base+val[v.first];
dfs_pre(v.first,x);
}
}
inline int up(int x,int d) {for(int i=0;i<L;i++) if((d>>i)&1) x=fa[x][i]; return x;}
inline int lca(int x,int y) {
if(dep[x]<dep[y]) swap(x,y);
if(dep[x]>dep[y]) x=up(x,dep[x]-dep[y]);
if(x==y) return x;
for(int i=L-1;~i;i--) if(fa[x][i]^fa[y][i]) x=fa[x][i], y=fa[y][i];
return fa[x][0];
}
const int H=2333333;
struct Hash_Map {
#define pii pair <ULL,int>
vector <pii> cont[H];
inline void insert(ULL x) {
int p=x%H;
for(int i=0;i<cont[p].size();++i)
if(cont[p][i].first==x) {++cont[p][i].second; return;}
cont[p].push_back(pii(x,1));
}
inline int ask(ULL x) {
int p=x%H;
for(int i=0;i<cont[p].size();++i)
if(cont[p][i].first==x) return cont[p][i].second;
return 0;
}
inline void del(ULL x) {
int p=x%H;
for(int i=0;i<cont[p].size();++i)
if(cont[p][i].first==x) {
if(cont[p][i].second>1) --cont[p][i].second;
else cont[p].pop_back();
return;
}
}
#undef pii
} hs;
int lim;
inline void dfs(int x,int f) {
f2[x]=fa[f2[x]][0];
if(dep[x]>lim) hs.insert(upv[x]-upv[f2[x]]*pw[lim]);
while(qry[x].size() && qry[x].back().l==lim) {
data v=qry[x].back(); qry[x].pop_back();
ans[v.id]+=hs.ask(v.vv)*v.base;
}
for(auto v:edge[x]) if(v.first^f) dfs(v.first,x);
if(dep[x]>lim) hs.del(upv[x]-upv[f2[x]]*pw[lim]);
}
int main() {
scanf("%d",&n);
for(int i=1;i<n;i++) {
int x,y; char ch[3];
scanf("%d%d%s",&x,&y,ch+1);
edge[x].push_back(pii(y,ch[1]));
edge[y].push_back(pii(x,ch[1]));
}
pw[0]=1;
for(int i=1;i<=n;i++) pw[i]=pw[i-1]*base;
dfs_pre(1,0);
scanf("%d",&m);
for(int i=1;i<=m;i++) {
int x,y,f;
scanf("%d%d",&x,&y);
f=lca(x,y);
static char ch[N];
scanf("%s",ch+1); int len=strlen(ch+1);
if(dep[x]-dep[f]>=len) {
ULL val=0;
for(int j=1;j<=len;j++) val=val+ch[j]*pw[j-1];
qry[x].push_back(data(val,i,1,len));
qry[up(x,dep[x]-dep[f]-len+1)].push_back(data(val,i,-1,len));
}
if(dep[y]-dep[f]>=len) {
ULL val=0;
for(int j=0;j<len;j++) val=val+ch[len-j]*pw[j];
qry[y].push_back(data(val,i,1,len));
qry[up(y,dep[y]-dep[f]-len+1)].push_back(data(val,i,-1,len));
}
static int seq[300], tl;
if(x!=f && y!=f && len>1) {
tl=0;
int u=up(x,max(0,dep[x]-dep[f]-len+1));
for(;u!=f;u=fa[u][0]) seq[++tl]=u;
int top=tl;
u=up(y,max(0,dep[y]-dep[f]-len+1));
for(;u!=f;u=fa[u][0]) seq[++tl]=u;
if(tl<len) continue;
reverse(seq+top+1,seq+tl+1);
ULL v=0,v2=0;
for(int j=0;j<len;j++) v=v+ch[len-j]*pw[j];
for(int j=1;j<=len;j++) v2=v2+val[seq[j]]*pw[len-j];
ans[i]+=(v==v2);
for(int j=len+1;j<=tl;++j) {
v2=v2-val[seq[j-len]]*pw[len-1];
v2=v2*base+val[seq[j]];
ans[i]+=(v==v2);
}
}
}
for(int i=1;i<=n;i++) sort(qry[i].begin(),qry[i].end());
for(int i=1;i<=100;i++) {
lim=i;
dfs(1,0);
}
for(int i=1;i<=m;i++) W(ans[i]), putchar('\n');
}