题意:给你一棵树,让你输出节点u到v的最短路径上子序列ABCAB的个数;
思路:我们建立树上可持续化线段树,那么这颗树的叶子节点上的那颗线段树就保存了这条链的消息,对于两个节点,之间的ABCAB的个数,就等于第u个节点的线段树dep【lca】到dep【u】的区间和加第v颗线段树dep【lca】到dep【v】的区间和的和。需要注意的是位于左边的那条链的答案需要反着求。
#include<bits/stdc++.h> using namespace std; const int maxn=3e4+10,mod=10007; char a[maxn]; int f[maxn][20],dep[maxn],rt[maxn],n,cnt,ls[maxn*20],rs[maxn*20]; struct node{ int cat, A, AB, ABC, ABCB, B, BC, BCB, BCBA, C, CB, CBA, BA; node operator+(const node &t) const { node tmp; tmp.cat = (cat + t.cat + A * t.BCBA + AB * t.CBA + ABC * t.BA + ABCB * t.A) % mod; tmp.A = (A + t.A) % mod; tmp.AB = (AB + t.AB + A * t.B) % mod; tmp.ABC = (ABC + t.ABC + A * t.BC + AB * t.C) % mod; tmp.ABCB = (ABCB + t.ABCB + A * t.BCB + AB * t.CB + ABC * t.B) % mod; tmp.B = (B + t.B) % mod; tmp.BC = (BC + t.BC + B * t.C) % mod; tmp.BCB = (BCB + t.BCB + B * t.CB + BC * t.B) % mod; tmp.BCBA = (BCBA + t.BCBA + B * t.CBA + BC * t.BA + BCB * t.A) % mod; tmp.C = (C + t.C) % mod; tmp.CB = (CB + t.CB + C * t.B) % mod; tmp.CBA = (CBA + t.CBA + C * t.BA + CB * t.A) % mod; tmp.BA = (BA + t.BA + B * t.A) % mod; return tmp; } }tr[maxn*20]; vector<int>G[maxn]; #define mid (l+r)/2 void up(int& o,int pre,int l,int r,int p,char c) { o=++cnt; ls[o]=ls[pre]; rs[o]=rs[pre]; if(l==r) { if(c=='A') tr[o].A = 1; else if(c=='B') tr[o].B =1; else if(c=='C') tr[o].C =1; return ; } if(p<=mid)up(ls[o],ls[pre],l,mid,p,c); else up(rs[o],rs[pre],mid+1,r,p,c); tr[o]=tr[ls[o]] + tr[rs[o]]; } void dfs(int u,int fa) { f[u][0]=fa; dep[u]=dep[fa]+1; for(int i=1;i<18;i++) { f[u][i]=f[f[u][i-1]][i-1]; } up(rt[u],rt[fa],1,n,dep[u],a[u]); for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(v==fa)continue; dfs(v,u); } } node qu(int o,int l,int r,int L,int R) { if(l>=L&&r<=R)return tr[o]; if(R<=mid)return qu(ls[o],l,mid,L,R); if(L>mid)return qu(rs[o],mid+1,r,L,R); else return qu(ls[o],l,mid,L,R) + qu(rs[o],mid+1,r,L,R); } int Lca(int u,int v) { if(dep[u]<dep[v])swap(u,v); assert(dep[u] >= dep[v]); for(int i=17;~i;i--) { if(dep[f[u][i]]>=dep[v])u=f[u][i]; } assert(dep[v]==dep[u]); if(u==v)return u; for(int i=17;~i;i--) { if(f[u][i]!=f[v][i]) { u=f[u][i]; v=f[v][i]; } } return f[u][0]; } int main() { int q; scanf("%d %d",&n,&q); scanf("%s",a+1); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs(1,0); while(q--) { int u,v; scanf("%d %d",&u,&v); int lca=Lca(u,v); if(u==lca||v==lca) { node an; if(u==lca)swap(u,v); an=qu(rt[u],1,n,dep[v],dep[u]); cout<<an.cat%mod<<'\n'; } else { int ans; node t1=qu(rt[u],1,n,dep[lca],dep[u]); node t2=qu(rt[v],1,n,dep[lca]+1,dep[v]); ans = (t1.cat + t2.cat + t1.A * t2.BCBA + t1.BA * t2.CBA + t1.CBA * t2.BA + t1.BCBA * t2.A) % mod; printf("%d\n",ans); } } }
ABCAB
最新推荐文章于 2024-03-20 09:34:03 发布