题面

初见广义SAM

建立广义SAM,每次把询问走一遍,最终走到节点的子树里的猫老师都被这次点名点到

这样DFS parent树打时间戳记录入栈出栈时间,把问题转化成一个序列问题:给一个若干种颜色构成的序列和一些区间,询问:

1.每个区间里有多少种颜色— —直接莫队

2.每种颜色被多少区间包含— —同样是莫队,当某种颜色消失时从它上次出现开始的区间到现在的区间都包含了它

 #include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<unordered_map>
using namespace std;
const int N=;
struct a
{
int l,r;
int idx,blo;
}q[N];
unordered_map<int,int> trs[N];
int fth[N],len[N],bel[N];
int p[N],noww[N],goal[N];
int ins[N],ots[N],col[N];
int qry[N],bkt[N],las[N],ans1[N],ans2[N];
int n,m,lp,rp,ll,rd,lst,sqr,cnt,tot,dfn,ans;
bool cmp(a x,a y)
{
return x.blo==y.blo?x.r<y.r:x.blo<y.blo;
}
void Link(int f,int t)
{
noww[++cnt]=p[f];
goal[cnt]=t,p[f]=cnt;
}
void Insert(int ch)
{
int nde=lst,newn=++tot;
lst=newn,len[newn]=len[nde]+;
while(nde&&!trs[nde][ch])
trs[nde][ch]=newn,nde=fth[nde];
if(!nde)
fth[newn]=;
else
{
int tran=trs[nde][ch];
if(len[tran]==len[nde]+)
fth[newn]=tran;
else
{
int rnde=++tot;
len[rnde]=len[nde]+,trs[rnde]=trs[tran];
fth[rnde]=fth[tran],fth[tran]=fth[newn]=rnde;
while(nde&&trs[nde][ch]==tran)
trs[nde][ch]=rnde,nde=fth[nde];
}
}
}
void DFS(int nde)
{
ins[nde]=++dfn,col[dfn]=bel[nde];
for(int i=p[nde];i;i=noww[i])
DFS(goal[i]); ots[nde]=dfn;
}
void Add(int tsk,int typ)
{
if(tsk)
if(++bkt[tsk]==)
ans++,las[tsk]=typ;
}
void Delete(int tsk,int typ)
{
if(tsk)
if(!(--bkt[tsk]))
ans--,ans2[tsk]+=typ-las[tsk];
}
int main()
{
scanf("%d%d",&n,&m),tot=;
for(int i=;i<=n;i++)
{
scanf("%d",&ll),lst=;
for(int j=;j<=ll;j++)
scanf("%d",&rd),Insert(rd),bel[lst]=i;
scanf("%d",&ll),lst=;
for(int j=;j<=ll;j++)
scanf("%d",&rd),Insert(rd),bel[lst]=i;
}
for(int i=;i<=tot;i++) Link(fth[i],i);
DFS(),sqr=sqrt(tot)+;
for(int i=;i<=m;i++)
{
scanf("%d",&ll);
for(int j=;j<=ll;j++)
scanf("%d",&qry[j]);
int nde=;
for(int j=;j<=ll;j++)
{
nde=trs[nde][qry[j]];
if(!nde) break;
}
q[i].l=ins[nde],q[i].r=ots[nde];
q[i].idx=i,q[i].blo=(q[i].l-)/sqr+;
}
sort(q+,q++m,cmp),lp=,rp=;
for(int i=;i<=m;i++)
{
while(lp<q[i].l) Delete(col[lp++],i);
while(lp>q[i].l) Add(col[--lp],i);
while(rp<q[i].r) Add(col[++rp],i);
while(rp>q[i].r) Delete(col[rp--],i);
ans1[q[i].idx]=ans;
}
for(int i=lp;i<=rp;i++) Delete(col[i],m+);
for(int i=;i<=m;i++) printf("%d\n",ans1[i]);
for(int i=;i<=n;i++) printf("%d ",ans2[i]);
return ;
}
05-11 21:52