hdu5081
题意有点绕,不过读懂了之后并不难
以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);
}
}
}
}
hdu5081的更多相关文章
随机推荐
- 【Linux】——实用命令
[前言] Linux的命令可以分为文件存取.目录操作.进程管理.权限管理.磁盘操作等内容,大量的命令方便了用户进行更快捷更高效的工作.但有一点需要说明的是,如果不采用linux的命令,也可以完成相应的 ...
- MYSQL 服务无法启动,错误日志:InnoDB: .\ibdata1 must be writable
这几天安装MYSQL 5.7版本的时候,出现了服务无法启动的问题,尝试了各种修改配置文件my.ini的方法都不行,查看到错误日志,一般错误日志在C:\Program Files\MySQL\MySQL ...
- 【SQLAlchemy】SQLAlchemy技术文档(中文版)(中)
10.建立联系(外键) 是时候考虑怎样映射和查询一个和Users表关联的第二张表了.假设我们系统的用户可以存储任意数量的email地址.我们需要定义一个新表Address与User相关联. from ...
- oracle分区技术提高查询效率
概述: 当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区.表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上存放到多个表空间(物理文件 ...
- [NOIP2018 TG D2T1]旅行
题目大意:$NOIP\;TG\;D2T1$ 题解:一棵树的很简单,第一个点一定是$1$,只需要对每个节点,找最小的没有访问过的节点访问即可,我写的是$O(n\log_2n)$. 考虑基环树的部分,一个 ...
- Eclipse中的引用项目报Could not find *.apk!解决办法
百度上很多关于Could not find *.apk!这种编译报错的解决帖子,但是笔主在这里主要说一下在 引用工程项目的场景 下报这个错误消息的问题(不影响本项目的正常编译运行!). 笔主刚从谷歌上 ...
- 如何在Javascript中利用封装这个特性
对于熟悉C#和Java的兄弟们,面向对象的三大思想(封装,继承,多态)肯定是了解的,那么如何在Javascript中利用封装这个特性呢? 我们会把现实中的一些事物抽象成一个Class并且把事物的属性( ...
- How do I see what character set a database / table / column is in MySQL?
Q: How do I see what the character set that a MySQL database, table and column are in? Is there some ...
- [Usaco2015 dec]Max Flow 树上差分
[Usaco2015 dec]Max Flow Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 353 Solved: 236[Submit][Sta ...
- centos7 mysql cluster集群搭建基于docker
1.准备 mn:集群管理服务器用于管理集群的其他节点.我们可以从管理节点创建和配置集群上的新节点.重新启动.删除或备份节点. db2/db3:这是节点间同步和数据复制的过程发生的层. db4/db5: ...