首页 技术 正文
技术 2022年11月14日
0 收藏 374 点赞 5,017 浏览 2398 个字

题意有点绕,不过读懂了之后并不难

以Si结尾容易想到ac自动机,建好ac自动机并将fail指针反向即可得到一棵树

那么操作1就是将若干个子树的并中的节点全部权值+1

操作2就是将求若干个节点到根的路径的并中的节点的权值和

操作1不难用dfs序将子树并转化为区间并然后线段树区间加

操作2呢,我们进行树链剖分,对于每条重链,在重链头记录一下这条重链之前询问到哪个位置了

因为每个点到根的路径都是若干重链的若干前缀,这样问题就解决了

 #include<bits/stdc++.h> using namespace std;
typedef long long ll;
int go[][],a[],fa[],laz[],l[],r[],c[],q[],s[],nex[],top[],f[],d[];
int n,m,k,t,ch;
vector<int> g[];
bool v[];
ll tr[];
char ss[]; bool cmp(int a,int b)
{
if (l[a]==l[b]) return r[a]<r[b];
return l[a]<l[b];
} void bfs()
{
int h=,r=;
for (int i=; i<; i++)
if (go[][i])
{
g[].push_back(go[][i]+);
q[++r]=go[][i];
}
while (h<=r)
{
int x=q[h++];
for (int i=; i<; i++)
if (go[x][i])
{
int y=go[x][i];
q[++r]=y;
int j=f[x];
while (j>&&!go[j][i]) j=f[j];
f[y]=go[j][i];
g[go[j][i]+].push_back(y+);
}
}
} void dfs(int x)
{
s[x]=;
for (int i=; i<g[x].size(); i++)
{
int y=g[x][i];
// cout <<x<<" "<<y<<endl;
d[y]=d[x]+;
fa[y]=x;
dfs(y);
s[x]+=s[x];
}
} void get(int x)
{
l[x]=++t;
int q=;
for (int i=; i<g[x].size(); i++)
{
int y=g[x][i];
if (s[y]>s[q]) q=y;
}
if (q)
{
top[q]=top[x];
get(q);
}
nex[x]=q;
for (int i=; i<g[x].size(); i++)
{
int y=g[x][i];
if (y!=q)
{
top[y]=y;
get(y);
}
}
r[x]=t;
} void push(int i,int l,int r)
{
int m=(l+r)>>;
tr[i*]+=1ll*laz[i]*(m+-l);
tr[i*+]+=1ll*laz[i]*(r-m);
laz[i*]+=laz[i];
laz[i*+]+=laz[i];
laz[i]=;
} void add(int i,int l,int r,int x,int y)
{
if (x<=l&&y>=r)
{
tr[i]+=(r-l+);
laz[i]++;
}
else {
int m=(l+r)>>;
if (laz[i]) push(i,l,r);
if (x<=m) add(i*,l,m,x,y);
if (y>m) add(i*+,m+,r,x,y);
tr[i]=tr[i*]+tr[i*+];
}
} ll ask(int i,int l,int r,int x,int y)
{
if (x<=l&&y>=r) return tr[i];
else {
int m=(l+r)>>; ll s=;
if (laz[i]) push(i,l,r);
if (x<=m) s+=ask(i*,l,m,x,y);
if (y>m) s+=ask(i*+,m+,r,x,y);
return s;
}
} ll getans(int x)
{
ll s=;
while (x)
{
int y=top[x];
if (!c[y]||d[c[y]]>d[x]) return s;
s+=ask(,,n,l[c[y]],l[x]);
if (c[y]!=y) {c[y]=nex[x]; return s;}
c[y]=nex[x]; x=fa[y];
if (!v[y])
{
q[++t]=y;
v[y]=;
}
}
return s;
} void clr()
{
for (int i=; i<=t; i++)
{
int x=q[i];
v[x]=; c[x]=x;
}
t=;
} int main()
{
int cas;
scanf("%d",&cas);
while (cas--)
{
scanf("%d",&n);
memset(go,,sizeof(go));
memset(f,,sizeof(f));
for (int i=; i<=n; i++)
{
int x;
scanf("%d%s",&x,&ss);
go[x-][ss[]-'a']=i-;
}
for (int i=; i<=n; i++) g[i].clear();
bfs(); t=;
dfs(); top[]=; get();
for (int i=; i<=n; i++) c[i]=i;
memset(tr,,sizeof(tr));
memset(laz,,sizeof(laz));
scanf("%d",&m); t=;
for (int i=; i<=m; i++)
{
scanf("%d",&ch);
scanf("%d",&k);
for (int j=; j<=k; j++) scanf("%d",&a[j]);
if (ch==)
{
sort(a+,a++k,cmp);
int b=l[a[]],e=r[a[]];
for (int j=; j<=k; j++)
{
if (e<l[a[j]])
{
add(,,n,b,e);
b=l[a[j]];
e=r[a[j]];
}
else e=max(e,r[a[j]]);
}
add(,,n,b,e);
}
else {
ll ans=;
for (int j=; j<=k; j++) ans+=getans(a[j]);
clr();
printf("%lld\n",ans);
}
}
}
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,078
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,553
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,402
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,177
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,814
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,898