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的更多相关文章
随机推荐
- PAT 1089 狼人杀-简单版
https://pintia.cn/problem-sets/994805260223102976/problems/1038429385296453632 以下文字摘自<灵机一动·好玩的数学& ...
- Windows 64下elasticsearch-1.7.1集群 安装、启动、停止
elasticsearch-1.7.1 (es Windows 64) 安装.启动.停止的详细记录 https://blog.csdn.net/qq_27093465/article/details/ ...
- Codeforces Round #390 (Div. 2) E(bitset优化)
题意就是一个给出2个字符矩阵,然后进行匹配,输出每个位置的匹配的结果 (超出的部分循环处理) 一种做法是使用fft,比较难写,所以没有写 这里使用一个暴力的做法,考虑到一共只出现26个字符 所以使用一 ...
- 【题解】HNOI2010合唱队
我果然还是太弱了呜呜呜……洛谷P3205 区间dp:注意到一段区间最两侧的人必然是最后加入队伍的所以由此我们可以分成两种情况来讨论. 一种是最后一个加入的人是左边的,另一种是右边的.那么状态:dp[i ...
- [CF15C]Industrial Nim
题目大意:有$n$个采石场,每行一个$m_i$一个$x_i$,表示第$i$个采石场有$m_i$辆车,这个采石场中车中的石子为从$x_i$开始的自然数.Nim游戏若先手赢输出"tolik&qu ...
- HttpClient测试类请求端和服务端即可能出现乱码的解决
junit HttpClient 请求端 代码: package com.taotao.httpclient; import java.util.ArrayList; import java.util ...
- Welcome to ShangHai <码农上漂记>
来上海这边快三周了,一切都还算顺利,多亏了朋友们的帮助,要不就得街头打地铺了.对于上海这样的大都市,年轻的我们都想挤一挤,凑凑热闹,实现自己的小小抱负.然而不是每个人都混的起的.以前的我还总想着来大城 ...
- 【uva11732-"strcmp()" Anyone?】Trie
http://acm.hust.edu.cn/vjudge/problem/28438 题意:给定n个字符串,问用strcmp函数比较这些字符串共用多少次比较. 题解: 插入一个‘#’作为字符串的结束 ...
- 分布式缓存Memcache
Memcached是分布式的,也就是说它不是本地的.它基于网络连接(当然它也可以使用localhost)方式完成服务,本身它是一个独立于应用的程序或守护进程(Daemon方式). Memcached使 ...
- [bzoj4034][HAOI2015]树上操作——树状数组+dfs序
Brief Description 您需要设计一种数据结构支持以下操作: 把某个节点 x 的点权增加 a . 把某个节点 x 为根的子树中所有点的点权都增加 a . 询问某个节点 x 到根的路径中所有 ...