【省选模拟】20/05/20_i++

  • 考虑序列上的情况,一次操作就是交换两个前缀和,那么若所有前缀和均【省选模拟】20/05/20_后缀_02,答案就是逆序对数之和,考虑将前缀和的定义扩展到环,显然有【省选模拟】20/05/20_后缀_03否则(若为 0 必须全部为 0)不合法
    我们定义【省选模拟】20/05/20_i++_04,考虑交换两个数会让【省选模拟】20/05/20_#define_05减少 1, 而最后要求【省选模拟】20/05/20_#define_06,故我们只需要求出【省选模拟】20/05/20_#define_05即可
    【省选模拟】20/05/20_后缀_08
    注意到这是一个三维偏序问题,可以【省选模拟】20/05/20_i++_09求解
    又发现可以忽略掉【省选模拟】20/05/20_i++_10的限制,在【省选模拟】20/05/20_后缀_11统计,【省选模拟】20/05/20_#define_12的贡献差 1,统计【省选模拟】20/05/20_#define_13的个数即可,懒得改了
#include<bits/stdc++.h>
#define cs const
#define pb push_back
#define fi first
#define se second
#define mp make_pair
using namespace std;
namespace IO{
cs int Rlen=1<<22|1;
inline char gc(){
static char buf[Rlen],*p1,*p2;
(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));
return p1==p2?EOF:*p1++;
} int read(){
int x=0; char c=gc(); bool f=false;
while(!isdigit(c)) f=c=='-', c=gc();
while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48), c=gc();
return f?-x:x;
}
} using namespace IO;
typedef pair<int, int> pi;
typedef long long ll;
cs int N = 2e5 + 50;
int n, m, a[N], sz;
ll sm[N], bin[N], A[N], B[N], Ans;
bool cmp(cs int &a, cs int &b){ return B[a] < B[b]; }
namespace bit{
int n, ct[N]; ll sm[N];
void clr(int sz){
n=sz; memset(ct,0,sizeof(int)*(n+1));
memset(sm,0,sizeof(ll)*(n+1));
}
void add(int x, int a, int b){ for(;x<=n;x+=x&-x) ct[x]+=b, sm[x]+=a; }
int qct(int x){ int as=0; for(;x;x-=x&-x) as+=ct[x]; return as; }
ll qsm(int x){ ll as=0; for(;x;x-=x&-x) as+=sm[x]; return as; }
}
namespace _bit{
int n, c[N];
void clr(int sz){
n=sz; memset(c,0,sizeof(int)*(n+1));
} void add(int x, int v){ for(;x<=n;x+=x&-x) c[x]+=v; }
int ask(int x){ int as=0; for(;x;x-=x&-x) as+=c[x]; return as; }
}
void work(int l, int r){
if(l==r) return; int mid=(l+r)>>1;
static int L[N], R[N]; int tl=0, tr=0;
for(int i=l; i<=mid; i++) L[++tl]=i;
for(int i=mid+1; i<=r; i++) R[++tr]=i;
sort(L+1,L+tl+1,cmp);
sort(R+1,R+tr+1,cmp); int j=1;
// cout<<"work "<<l<<" "<<r<<" "<<mid<<endl;
for(int i=1; i<=tr; i++){
while(j<=tl && B[L[j]]<=B[R[i]]){
if(L[j]>n) Ans-=_bit::ask(sm[L[j]-n]-1);
else Ans+=_bit::ask(sm[L[j]]-1); ++j;
} _bit::add(sm[R[i]],1);
} while(j<=tl){
if(L[j]>n) Ans-=_bit::ask(sm[L[j]-n]-1);
else Ans+=_bit::ask(sm[L[j]]-1); ++j;
} for(int i=1; i<=tr; i++) _bit::add(sm[R[i]],-1);
work(l,mid); work(mid+1,r);
}
void Main(){
n=read(); bool ok = true; Ans=0; sz=0;
for(int i=1; i<=n; i++) a[i]=read(), ok &= !a[i];
for(int i=1; i<=n+n; i++)
sm[i]=sm[i-1]+a[(i-1)%n+1], bin[++sz]=sm[i];
if(sm[n]<0) return puts("-1"), void();
if(sm[n]==0) return ok ? puts("0") : puts("-1"), void();
for(int i=1; i<=n+n; i++){
A[i]=sm[i]>=0?sm[i]/sm[n]:(sm[i]/sm[n]-(sm[i]%sm[n]!=0));
B[i]=(sm[i]%sm[n]+sm[n])%sm[n];
}
sort(bin+1,bin+sz+1); sz=unique(bin+1,bin+sz+1)-(bin+1);
for(int i=1; i<=n+n; i++) sm[i]=lower_bound(bin+1,bin+sz+1,sm[i])-bin;
bit :: clr(sz);
for(int i=n+n; i>=n+1; i--) bit :: add(sm[i],A[i],1);
for(int i=n; i>=1; i--){
bit :: add(sm[i+n],-A[i+n],-1);
Ans += (ll)bit :: qct(sm[i]) * A[i] - bit :: qsm(sm[i]);
bit :: add(sm[i],A[i],1);
} _bit :: clr(sz); work(1,n+n); cout<<Ans<<'\n';
}
int main(){
#ifdef FSYolanda
freopen("sequence.in","r",stdin);
// freopen("sequence.out","w",stdout);
#endif
int T=read();
while(T--) Main(); return 0;
}

【省选模拟】20/05/20_#define_14

  • 压一下最后一列的状态,代点值写成矩阵乘法的形式,然后【省选模拟】20/05/20_后缀_15回去即可
#include<bits/stdc++.h>
#define cs const
#define pb push_back
#define poly vector<int>
using namespace std;
typedef unsigned long long ull;
cs int Mod = 998244353;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(int &a, int b){ a = add(a,b); }
void Dec(int &a, int b){ a = dec(a,b); }
void Mul(int &a, int b){ a = mul(a,b); }
int ksm(int a, int b){ int as=1; for(;b;b>>=1,a=mul(a,a)) if(b&1) as=mul(as,a); return as; }
void output(poly a){ for(int i=0; i<(int)a.size(); i++) cout<<a[i]<<" "; puts(""); }
cs int N = 1<<17|5, K=17;
int n, m, k, a[N], iv[N], *w[K+1];
void NTT_init(){
for(int i=1; i<=K; i++) w[i]=new int [1<<(i-1)];
int wn=ksm(3,(Mod-1)/(1<<K)); w[K][0]=1;
for(int i=1; i<(1<<(K-1)); i++) w[K][i]=mul(w[K][i-1],wn);
for(int i=K-1;i;i--) for(int j=0; j<(1<<(i-1)); j++) w[i][j]=w[i+1][j<<1];
iv[0]=iv[1]=1; for(int i=2; i<=(1<<K); i++) iv[i]=mul(Mod-Mod/i,iv[Mod%i]);
} int up, bit, rv[N];
void init(int dg){
up=1, bit=0; while(up<dg) up<<=1,++bit;
for(int i=0; i<up; i++) rv[i]=(rv[i>>1]>>1)|((i&1)<<(bit-1));
}
void NTT(poly &a, int typ=1){
for(int i=0; i<up; i++) if(i<rv[i]) swap(a[i],a[rv[i]]);
for(int i=1,l=1; i<up; i<<=1,++l)
for(int j=0; j<up; j+=(i<<1))
for(int k=0; k<i; k++){
int x=a[k+j], y=mul(w[l][k],a[k+j+i]);
a[k+j]=add(x,y); a[k+j+i]=dec(x,y);
} if(typ==-1){
reverse(a.begin()+1,a.end());
for(int i=0,iv=ksm(up,Mod-2); i<up; i++) Mul(a[i],iv);
}
}
cs int M = 9; int D;
struct mat{
int a[M][M];
mat(){ memset(a,0,sizeof(a)); }
void I(){ for(int i=0; i<D; i++) a[i][i]=1; }
mat operator * (cs mat &A){
mat B; for(int i=0; i<D; i++)
for(int j=0; j<D; j++){
ull x = 0;
for(int k=0; k<D; k++) x += 1ull * a[i][k] * A.a[k][j];
B.a[i][j] = x % Mod;
} return B;
}
};
mat mat_pw(mat A, int b){
mat as; as.I();
for(;b;b>>=1,A=A*A) if(b&1) as=as*A; return as;
}
mat cope(int x){
mat now;
if(n <= 2){
for(int i=0; i<D; i++)
for(int j=0; j<D; j++)
if(i && !(i & j)) now.a[i][j] = x;
else now.a[i][j] = 1; return now;
}
for(int i=0; i<D-1; i++)
for(int j=0; j<D-1; j++){
if(j == 5 && (i != 5 && i != 7)) continue;
if(i && !(i & j)) now.a[i][j] = x;
else now.a[i][j] = 1;
} for(int j = 0; j < D; j++){
if(j==0||j==2) now.a[8][j] = mul(x,x);
if(j==1||j==3||j==4||j==6) now.a[8][j] = x;
if(j==7) now.a[8][j]=1;
} for(int i = 0; i < D; i++){
if(i==0||i==1||i==4||i==3||i==6||i==8) now.a[i][8] = 1;
if(i==2) now.a[i][8] = x;
} return now;
}
poly f[9];
int main(){
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
scanf("%d%d%d",&n,&m,&k);
NTT_init(); int dg = 0;
if(n == 1) D = 2, dg = (m >> 1) + 2;
if(n == 2) D = 4, dg = m + 2;
if(n == 3) D = 9, dg = (n * m >> 1) + 2;
int t=1; while(t<dg) t<<=1;
int wn=ksm(3,(Mod-1)/t); init(t);
for(int i=0,mt=1; i<t; i++){
mat now = cope(mt); now = mat_pw(now, m);
for(int j = 0; j < D; j++) f[j].pb(now.a[0][j]);
Mul(mt,wn);
} int as = 0;
for(int i = 0; i < D; i++){
NTT(f[i],-1);
if(i==0) Add(as, k<(int)f[i].size() ? f[i][k] : 0);
if(i && i<8) Add(as, k<=(int)f[i].size() ? f[i][k-1] : 0);
if(k>1 && i==8) Add(as, k+1<=(int)f[i].size() ? f[i][k-2] : 0);
} cout << as; return 0;
}

【省选模拟】20/05/20_后缀_16

  • 直上直下的可以简单处理
  • 考虑经过【省选模拟】20/05/20_后缀_17的,发现需要处理从【省选模拟】20/05/20_后缀_17往下的极长的满足其为查询串的后缀的长度,这样只需要对两边的极长串的【省选模拟】20/05/20_i++_19拼接即可,拼接可以用【省选模拟】20/05/20_i++_19定理快速求
  • 下面考虑预处理这个极长的从【省选模拟】20/05/20_后缀_17向下的前缀,我们在这个字符串的后缀数组中二分出它的位置,然后求出它与任意一个后缀的最长公共前缀,那么显然合法的极长后缀是这个并不合法的后缀的【省选模拟】20/05/20_i++_19,我们可以预处理【省选模拟】20/05/20_#define_23的倍增数组跳过去,上述均可在【省选模拟】20/05/20_后缀_24的时间内解决,第一次自己码了个【省选模拟】20/05/20_后缀_25的代码…
#include<bits/stdc++.h>
#define cs const
#define pb push_back
#define fi first
#define se second
#define mp make_pair
using namespace std;
typedef long long ll;
namespace IO{
cs int Rlen=1<<22|1;
inline char gc(){
static char buf[Rlen],*p1,*p2;
(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));
return p1==p2?EOF:*p1++;
} int read(){
int x=0; char c=gc(); bool f=false;
while(!isdigit(c)) f=c=='-', c=gc();
while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48), c=gc();
return f?-x:x;
} int str(){
char c=gc(); while(isspace(c)) c=gc();
return c-'a';
} int Str(char *S){
char c=gc(); while(isspace(c)) c=gc();
int len=0; while('a'<=c&&c<='z') S[++len]=c, c=gc();
return len;
}
} using namespace IO;
// Hash work
typedef pair<int, int> pi;
cs int N = 2e5 + 50;
cs int M1 = 1e9 + 7, M2 = 998244353;
cs int B1 = 19260817, B2 = 17680321;
int add(int a, int b, int mod){ return a + b >= mod ? a + b - mod : a + b; }
int dec(int a, int b, int mod){ return a - b < 0 ? a - b + mod : a - b; }
int mul(int a, int b, int mod){ return 1ll * a * b % mod; }
pi operator + (pi a, pi b){ return mp(add(a.fi,b.fi,M1), add(a.se,b.se,M2)); }
pi operator - (pi a, pi b){ return mp(dec(a.fi,b.fi,M1), dec(a.se,b.se,M2)); }
pi operator * (pi a, pi b){ return mp(mul(a.fi,b.fi,M1), mul(a.se,b.se,M2)); }
bool operator == (pi a, pi b){ return a.fi == b.fi && a.se == b.se; }
pi pw[N]; void init_pw(int n){
pw[0]=mp(1,1); pw[1]=mp(B1,B2);
for(int i=2; i<=n; i++) pw[i] = pw[i-1] * pw[1];
}
int n, m, q, len[N], ps[N][2]; char tmp[N];
struct dat{ int l, r, dt; };
struct AC_Automaton{
int ch[N][26], nd, fail[N];
int ins(char *S, int len){
int u=0; for(int i=1,c; i<=len; i++){ c=S[i]-'a';
if(!ch[u][c]) ch[u][c]=++nd; u=ch[u][c]; } return u;
} int in[N], out[N], sgn; vector<int> G[N];
void dfs(int u){
in[u]=++sgn; for(int e=0,v; e<(int)G[u].size(); e++)
{ v=G[u][e]; dfs(v); } out[u]=sgn;
} void build(){
queue<int> q; for(int i=0; i<26; i++) if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty()){
int x=q.front(); q.pop(); for(int i=0; i<26; i++)
if(ch[x][i]) fail[ch[x][i]]=ch[fail[x]][i],q.push(ch[x][i]);
else ch[x][i]=ch[fail[x]][i];
} for(int i=1; i<=nd; i++) G[fail[i]].pb(i); dfs(0);
}
} AC[2];
struct BIT{
int c[N], n;
void add(int x, int v){ for(;x<=n;x+=x&-x) c[x]+=v; }
int ask(int x){ int as=0; for(;x;x-=x&-x) as+=c[x]; return as; }
int ask(int l, int r){ return ask(r)-ask(l-1); }
} bit[2];
// Part tree
vector<pi> G[N];
int an[N][22], o[N], dep[N], lg[N], Ans[N];
pi h[N]; // up to down
pi Has(int u, int v){ return h[u] - h[v] * pw[dep[u]-dep[v]]; }
void dfs(int u, int fa){
dep[u]=dep[fa]+1; an[u][0]=fa;
for(int i=1; i<=lg[dep[u]]; i++)
an[u][i]=an[an[u][i-1]][i-1];
for(int e=0,v,c; e<(int)G[u].size(); e++)
if((v=G[u][e].fi)!=fa){
c=G[u][e].se; o[v]=c;
h[v]=h[u]*pw[1]+mp(c,c); dfs(v,u);
}
} int LCA(int x, int y){
if(dep[x]<dep[y]) swap(x,y);
for(int i=lg[dep[x]];~i;i--)
if(dep[an[x][i]]>=dep[y]) x=an[x][i]; if(x==y) return x;
for(int i=lg[dep[x]];~i;i--)
if(an[x][i]!=an[y][i]) x=an[x][i], y=an[y][i];
return an[x][0];
} int jmp(int x, int d){
if(!d) return x; for(int i=lg[d];~i;i--)
if(d>=(1<<i)) x=an[x][i], d-=1<<i; return x;
}
struct qry{ int op, p, c; };
vector<qry> ql[N], qr[N];
void cope(int u, int fa, int nx, int ny){
bit[0].add(AC[0].in[nx],1);
bit[1].add(AC[1].in[ny],1);
for(int i=0; i<(int)qr[u].size(); i++){
qry x = qr[u][i]; int pt = ps[x.p][0];
Ans[x.c] += x.op * bit[0].ask(AC[0].in[pt], AC[0].out[pt]);
}
for(int i=0; i<(int)ql[u].size(); i++){
qry x = ql[u][i]; int pt = ps[x.p][1];
Ans[x.c] += x.op * bit[1].ask(AC[1].in[pt], AC[1].out[pt]);
}
for(int e=0,v; e<(int)G[u].size(); e++) if((v=G[u][e].fi)!=fa)
cope(v,u,AC[0].ch[nx][G[u][e].se],AC[1].ch[ny][G[u][e].se]);
bit[0].add(AC[0].in[nx],-1);
bit[1].add(AC[1].in[ny],-1);
}
struct Suffix_Array{
int n, m; string S;
int *SA, *rk, *y, *tmp, *bin; // suffix array
pi *h; // hash
int *nxt[22], *trs; // border
void copy(char *t, int len){
n = len; S = ' ';
for(int i=1; i<=n; i++) S += t[i];
}
void Kmp_work(){
for(int i=1; i+i<=n; i++) if(i<n-i+1) swap(S[i],S[n-i+1]);
for(int i=0; i<=lg[n]; i++) nxt[i] = new int[n+1]();
for(int i=2,j=0; i<=n; i++){
while(j && S[j+1]!=S[i]) j = nxt[0][j];
if(S[j+1] == S[i]) ++j; nxt[0][i] = j;
} for(int j=1; j<=lg[n]; j++)
for(int i=1; i<=n; i++) nxt[j][i]=nxt[j-1][nxt[j-1][i]];
trs = new int[n+1]();
for(int i=1; i<=n; i++){
if(nxt[0][i] && i-nxt[0][i] == nxt[0][i]-nxt[0][nxt[0][i]])
trs[i] = trs[nxt[0][i]]; else trs[i] = i;
} for(int i=1; i+i<=n; i++) if(i<n-i+1) swap(S[i],S[n-i+1]);
}
void Hash_work(){
h = new pi[n+1](); for(int i=1; i<=n; i++)
h[i] = h[i-1] * pw[1] + mp(S[i]-'a',S[i]-'a');
}
void radix_sort(){
for(int i=0; i<=m; i++) bin[i]=0;
for(int i=1; i<=n; i++) ++bin[rk[i]];
for(int i=1; i<=m; i++) bin[i]+=bin[i-1];
for(int i=n; i; i--) SA[bin[rk[y[i]]]--]=y[i];
}
void build(){
m = 128; SA = new int[n+1](); rk = new int[n+1]();
tmp = new int[n+1](); y = new int[n+1]();
bin = new int[max(n+1,1<<8)]();
for(int i=1; i<=n; i++) rk[i]=S[i], y[i]=i;
radix_sort(); for(int k=1; k<=n; k<<=1){
int ct=0; for(int i=n-k+1; i<=n; i++) y[++ct]=i;
for(int i=1; i<=n; i++) if(SA[i]>k) y[++ct]=SA[i]-k;
radix_sort(); swap(rk,tmp); rk[SA[1]]=1; int num=1;
for(int i=2; i<=n; i++){
if(tmp[SA[i]]==tmp[SA[i-1]] && tmp[SA[i]+k]==tmp[SA[i-1]+k])
rk[SA[i]] = num; else rk[SA[i]] = ++num;
} m = num;
}
}
pi Get(int l, int r){ return h[r] - h[l-1] * pw[r-l+1]; }
int lcp(int u, int v, int p){
int as=0, l=1, r=min(n-p+1,dep[u]-dep[v]);
while(l<=r){
int mid=(l+r)>>1;
if(Has(jmp(u,dep[u]-dep[v]-mid),v)==Get(p,p+mid-1))
l=mid+1, as=mid; else r=mid-1;
} return as;
}
bool chk(int u, int v, int p){
int len=lcp(u,v,SA[p]);
if(len==dep[u]-dep[v]) return false;
int nx=jmp(u,dep[u]-dep[v]-len-1);
return o[nx]>=S[SA[p]+len]-'a';
}
int fnd(int u, int v){
int l=1, r=n; while(l<r){
int mid=(l+r+1)>>1;
if(chk(u,v,mid)) l=mid; else r=mid-1;
} int pt = SA[l], mx = lcp(u,v,pt);
if(l<n && lcp(u,v,SA[l+1])>mx)
pt=SA[l+1], mx=lcp(u,v,pt);
if(mx==0) return 0;
if(mx==n-pt+1) return n-pt+1;
for(int i=lg[n];~i;i--){
int np=n-nxt[i][n-pt+1]+1;
if(!np) continue;
if(lcp(u,v,np)!=n-np+1) pt=np;
} return nxt[0][n-pt+1];
}
void fnd_border(int pt, vector<dat>&S){
while(pt){
int np = trs[pt];
if(pt==np) S.pb((dat){np,pt,0});
else S.pb((dat){np,pt,pt-nxt[0][pt]});
pt = nxt[0][np];
}
}
} My[N][2];
namespace Yolanda{
ll x, y;
int exgcd(int a, int b){
if(!b) return x=1,y=0,a;
int gc=exgcd(b,a%b); ll tx=y, ty=x-(ll)a/b*y;
x=tx; y=ty; return gc;
}
int ex_work(dat a, dat b, int len){
int c = b.l + a.r - len;
int u1 = (a.r - a.l) / a.dt, u2 = (b.r - b.l) / b.dt;
int gc = exgcd(a.dt, b.dt);
if(abs(c) % gc) return 0;
x = x * c / gc;
y = y * c / gc; y = -y;
int t1 = b.dt / gc, t2 = a.dt / gc;
ll dl = max((-x) / t1, (-y) / t2), dr = min((u1 - x) / t1, (u2 - y) / t2);
if(x > u1) dr = min(dr, (u1 - x + 1) / t1 - 1);
if(y > u2) dr = min(dr, (u2 - x + 1) / t2 - 1);
if(x < 0) dl = max(dl, (-x - 1) / t1 + 1);
if(y < 0) dl = max(dl, (-y - 1) / t2 + 1);
return max(0ll, dr - dl + 1);
}
int work(int u, int v, int l, int p){
int len = My[p][0].n;
int up = My[p][1].fnd(u,l);
int vp = My[p][0].fnd(v,l);
if(!up||!vp) return 0;
vector<dat> S, T; int as = 0;
My[p][1].fnd_border(up,S);
My[p][0].fnd_border(vp,T);
for(int i=0; i<S.size(); i++)
for(int j=0; j<T.size(); j++){
dat a = S[i], b = T[j];
if(a.r + b.r < len) break;
if(a.dt == 0 && b.dt == 0){ if(a.l + b.l == len) ++as; continue; }
if(a.dt == 0){ int c=len-a.l; if(b.l<=c&&c<=b.r&&(c-b.l)%b.dt==0) ++as; continue; }
if(b.dt == 0){ int c=len-b.r; if(a.l<=c&&c<=a.r&&(c-a.l)%a.dt==0) ++as; continue; }
if(a.dt == b.dt){
int c=len-a.r;
if(abs(b.l-c) % a.dt == 0){
int tl = max(c,b.l), tr = min(len-a.l, b.r);
if(tl<=tr) as += (tr-tl)/a.dt+1;
}
} else as += ex_work(a,b,len);
} return as;
}
}
int main(){
#ifdef FSYolanda
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
#endif
n=read(), m=read(), q=read(); init_pw(n);
for(int i=2; i<N; i++) lg[i]=lg[i>>1]+1;
for(int i=1,u,v,c; i<n; i++)
u=read(), v=read(), c=str(),
G[u].pb(mp(v,c)), G[v].pb(mp(u,c)); dfs(1,0);
for(int i=1; i<=m; i++){
len[i]=Str(tmp); My[i][0].copy(tmp,len[i]);
ps[i][0]=AC[0].ins(tmp,len[i]);
reverse(tmp+1,tmp+len[i]+1); My[i][1].copy(tmp,len[i]);
ps[i][1]=AC[1].ins(tmp,len[i]);
}
AC[0].build();
AC[1].build();
bit[0].n = AC[0].sgn;
bit[1].n = AC[1].sgn;
for(int i=1; i<=m; i++)
My[i][0].build(), My[i][1].build(),
My[i][0].Hash_work(), My[i][1].Hash_work(),
My[i][0].Kmp_work(), My[i][1].Kmp_work();
for(int i=1,u,v,p,x; i<=q; i++){
u=read(), v=read(), p=read();
int l = LCA(u,v);
if(dep[u] - dep[l] >= len[p]){
x = jmp(u, dep[u] - dep[l] - len[p] + 1);
ql[u].pb((qry){1,p,i});
ql[x].pb((qry){-1,p,i});
} if(dep[v] - dep[l] >= len[p]){
x = jmp(v, dep[v] - dep[l] - len[p] + 1);
qr[v].pb((qry){1,p,i});
qr[x].pb((qry){-1,p,i});
} if(u!=l && v!=l) Ans[i] += Yolanda :: work(u,v,l,p);
assert(Ans[i]>=0);
} cope(1,0,0,0);
for(int i=1; i<=q; i++) cout<<Ans[i]<<'\n', assert(Ans[i]>=0);
return 0;
}