【省选模拟】20/05/20

AA

  • 考虑序列上的情况,一次操作就是交换两个前缀和,那么若所有前缀和均 0\ge 0,答案就是逆序对数之和,考虑将前缀和的定义扩展到环,显然有 Sumn>0Sum_n>0 否则(若为 0 必须全部为 0)不合法
    我们定义 Ri=j>i,sumj<sumi1R_i=\sum_{j>i,sum_j<sum_i}1,考虑交换两个数会让 Ri\sum R_i 减少 1, 而最后要求 Ri=0\sum R_i=0,故我们只需要求出 Ri\sum R_i 即可
    Ri=j(i,i+n)SumiSumj1Sumn+1=j(i,i+n)SumiSumnSumjSumn+[Sumi%Sumn>Sumj%Sumn]R_i=\sum_{j\in(i,i+n)}\lfloor\frac{Sum_i-Sum_j-1}{Sum_n}\rfloor+1=\\\sum_{j\in(i,i+n)}\lfloor\frac{Sum_i}{Sum_n}\rfloor-\lfloor\frac{Sum_j}{Sum_n}\rfloor+[Sum_i\%Sum_n>Sum_j\%Sum_n]
    注意到这是一个三维偏序问题,可以 O(nlog2n)O(n\log ^2n) 求解
    又发现可以忽略掉 (i,i+n)(i,i+n) 的限制,在 [1,n][1,n] 统计,i,i+ni,i+n 的贡献差 1,统计 i<j,Sumi>Sumji<j,Sum_i>Sum_j 的个数即可,懒得改了
#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;
}

BB

  • 压一下最后一列的状态,代点值写成矩阵乘法的形式,然后 idftidft 回去即可
#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;
}

CC

  • 直上直下的可以简单处理
  • 考虑经过 lcalca 的,发现需要处理从 lcalca 往下的极长的满足其为查询串的后缀的长度,这样只需要对两边的极长串的 borderborder 拼接即可,拼接可以用 borderborder 定理快速求
  • 下面考虑预处理这个极长的从 lcalca 向下的前缀,我们在这个字符串的后缀数组中二分出它的位置,然后求出它与任意一个后缀的最长公共前缀,那么显然合法的极长后缀是这个并不合法的后缀的 borderborder,我们可以预处理 kmpkmp 的倍增数组跳过去,上述均可在 O(nlog2n)O(n\log^2n) 的时间内解决,第一次自己码了个 10k10k 的代码…
#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章