传送门
题意:
有一棵 n n n个点的无根树,第 i i i个点上有一个字符串 s i s_i si作为编号和一个权值 v i v_i vi,现在有 m m m次强制在线的询问/修改。
询问:给出一个字符串 S S S和一条路径 ( u , v ) (u,v) (u,v),路径上 i i i点的贡献是 s i s_i si在 S S S中出现次数* v i v_i vi,问总贡献。
时间复杂度: O ( n l o g 3 n ) , ∑ ∣ s i ∣ , ∑ ∣ S ∣ , n , m O(nlog^3n),\sum|s_i|,\sum|S|,n,m O(nlog3n),∑∣si∣,∑∣S∣,n,m同阶
修改:修改 v i v_i vi。
思路:
先把原树树剖了并求出 d f s dfs dfs序。
然后拿出所有的 s i s_i si建 a c ac ac自动机,然后求出 f a i l fail fail树的 d f s dfs dfs序。
考虑没有修改如何维护答案。
先利用树剖每条重链上 d f s dfs dfs序连续的性质分成 l o g log log次询问。
设这次询问允许出现的点的 d f s dfs dfs序编号区间是 [ q l , q r ] [ql,qr] [ql,qr]
我们拿 S S S在 a c ac ac自动机上面匹配,假设每次加一个字符之后转移到 p p p点,那么这一次的总贡献只跟 f a i l fail fail树上从 p p p到根节点路径上所有点有关。
考虑对于路径上每个点如何计算贡献:
限制:
对答案的贡献: v i v_i vi
思考一下如何同时维护一条链上面的答案。
我们可以对 f a i l fail fail树建一棵主席树,叶子 i i i记录原树 d f s dfs dfs序编号为 i i i的贡献,然后就变成了区间求和问题。
带修怎么做???
发现就是对子树里的所有主席树进行修改,用 b i t bit bit套主席树即可。
代码:
#include
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
typedef long long ll;
typedef pair<int,ll> pii;
inline char gc(){
static char buf[rlen],*ib,*ob;
(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
return ib==ob?-1:*ib++;
}
inline int read(){
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
inline ll readl(){
ll ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
}
inline vector<char>Read(){
vector<char>S;
S.push_back('0');
char ch=gc();
while(!isalpha(ch))ch=gc();
while(isalpha(ch))S.push_back(ch),ch=gc();
return S;
}
const int N=4e5+5,M=2e5+5;
inline int idx(char x){
switch(x){
case 'A':return 0;break;
case 'T':return 1;break;
case 'C':return 2;break;
case 'G':return 3;break;
default:return 4;break;
}
}
vector<char>s[M],t;
int rt[N],n,m,Tot=0;
ll a[M];
namespace sgt{
#define lc (son[p][0])
#define rc (son[p][1])
#define mid (l+r>>1)
int son[M*100][2],tot=0;
ll sum[M*100];
inline int lowbit(const int&x){return x&-x;}
inline void update(int&p,int o,int l,int r,int k,ll v){
if(!p)p=++tot;
sum[p]=sum[o]+v,lc=son[o][0],rc=son[o][1];
if(l==r)return;
k<=mid?update(lc,lc,l,mid,k,v):update(rc,rc,mid+1,r,k,v);
}
inline ll query(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return sum[p];
if(qr<=mid)return query(lc,l,mid,ql,qr);
if(ql>mid)return query(rc,mid+1,r,ql,qr);
return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
}
inline ll query(int p,int ql,int qr){ll ret=0;for(p;p;p^=lowbit(p))ret+=query(rt[p],1,n,ql,qr);return ret;}
inline void update(int p,pii a,int ff){for(p;p<=Tot+1;p+=lowbit(p))update(rt[p],rt[p],1,n,a.fi,a.se*ff);}
inline void update(int ql,int qr,pii a){update(ql,a,1),update(qr+1,a,-1);}
#undef lc
#undef rc
#undef mid
}
namespace acam{
int in[N],out[N],fail[N],tot=0,son[N][5],pos[M];
vector<int>e[N];
vector<pii>val[N];
inline void insert(pii a,vector<char>s){
ri p=0;
for(ri x,i=1,up=s.size()-1;i<=up;++i){
if(!son[p][x=idx(s[i])])son[p][x]=++Tot;
p=son[p][x];
}
pos[a.fi]=p;
val[p].push_back(a);
}
inline void getfail(){
static int q[N],hd,tl;
hd=1,tl=0;
for(ri i=0;i<5;++i)if(son[0][i])fail[q[++tl]=son[0][i]]=0;
while(hd<=tl){
int p=q[hd++];
for(ri i=0,v;i<5;++i){
if(!son[p][i]){son[p][i]=son[fail[p]][i];continue;}
fail[son[p][i]]=son[fail[p]][i];
q[++tl]=son[p][i];
}
e[fail[p]].push_back(p);
}
}
inline ll query(int ql,int qr,vector<char>s){
ll ret=0;
for(ri p=0,i=1,up=s.size()-1;i<=up;++i){
p=son[p][idx(s[i])];
ret+=sgt::query(in[p],ql,qr);
}
return ret;
}
inline void update(pii x){
int p=pos[x.fi];
sgt::update(in[p],out[p],x);
}
void dfs(int p){
in[p]=++tot;
for(ri i=0;i<e[p].size();++i)dfs(e[p][i]);
out[p]=tot;
for(ri i=0;i<val[p].size();++i)sgt::update(in[p],out[p],val[p][i]);
}
inline void init(){
getfail();
dfs(0);
}
}
namespace Tree{
int siz[M],hson[M],dep[M],top[M],fa[M],tot=0,num[M];
vector<int>e[M];
void dfs1(int p){
siz[p]=1;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa[p])continue;
fa[v]=p,dep[v]=dep[p]+1,dfs1(v),siz[p]+=siz[v];
if(siz[v]>siz[hson[p]])hson[p]=v;
}
}
void dfs2(int p,int tp){
top[p]=tp,num[p]=++tot;
acam::insert(pii(num[p],a[p]),s[p]);
if(!hson[p])return;
dfs2(hson[p],tp);
for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i])!=fa[p]&&v!=hson[p])dfs2(v,v);
}
inline ll query(int x,int y,vector<char>s){
ll ret=0;
while(top[x]^top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
ret+=acam::query(num[top[x]],num[x],s);
x=fa[top[x]];
}
if(dep[x]<dep[y])swap(x,y);
ret+=acam::query(num[y],num[x],s);
return ret;
}
inline void update(int p,ll v){
acam::update(pii(num[p],v-a[p]));
a[p]=v;
}
}
inline void init(){
Tree::dfs1(1);
Tree::dfs2(1,1);
acam::init();
}
ll opt,lastans=0;
int main(){
n=read(),opt=read();
for(ri i=1;i<=n;++i)s[i]=Read();
for(ri i=1;i<=n;++i)a[i]=read();
for(ri i=1,u,v;i<n;++i)u=read(),v=read(),Tree::e[u].push_back(v),Tree::e[v].push_back(u);
init();
for(ri tt=read(),x,y,op;tt;--tt){
op=read();
switch(op){
case 1:{
x=readl()^(lastans*opt),y=readl()^(lastans*opt);
t=Read();
cout<<(lastans=Tree::query(x,y,t))<<'\n';
break;
}
case 2:{
x=readl()^(lastans*opt),y=readl()^(lastans*opt);
Tree::update(x,y);
break;
}
}
}
return 0;
}