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

以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的更多相关文章

随机推荐

  1. 【EasyNetQ】- 控制队列名称

    在为队列生成名称时,EasyNetQ的默认行为是使用消息类型名称并将其附加到订阅ID.例如PartyInvitation,命名空间中的消息类型EasyNetQ.Tests.Integration将使用 ...

  2. javascript中将整数添加千位符号

    如果num是整数的话,将其转换成带千位符号的字符串: Number(num).toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' +  ','); 另 ...

  3. 【bzoj1922】[Sdoi2010]大陆争霸 堆优化Dijkstra

    题目描述 一张n个点m条边的图,通过每条边需要一定的时间.有一些限制条件,每个限制条件形如“x保护y”,表示到达y的最短时间不能小于到达x的最短时间(即如果在其之前到达,则需要等待至xd到达).问1到 ...

  4. Codeforce 721C DP+DAG拓扑序

    题意 在一个DAG上,从顶点1走到顶点n,路径上需要消费时间,求在限定时间内从1到n经过城市最多的一条路径 我的做法和题解差不多,不过最近可能看primer看多了,写得比较复杂和结构化 自己做了一些小 ...

  5. 【题解】CQOI2012交换棋子

    感受到网络流的强大了……这道题目的关键在于: 前后颜色不变的,流入流出的次数相等:原本是黑色的最后变成了白色,流出比流入次数多1:原本是白色最后变成黑色,流入比流出次数多一.所以我们将每一点拆成3个点 ...

  6. BZOJ2115 [Wc2011] Xor 【线性基】

    2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 3915  Solved: 1633 [Submit][Stat ...

  7. BZOJ_day4&&DSFZ_day1

    昨天坐火车才水了三道题... 25题 100810221041105110591087108811791191119212571303143218541876195119682140224224382 ...

  8. 【NOIP模拟赛】公主的朋友 区间染色问题

    这道题大家都用的分块,然而我发现这是一个经典算法:区间染色问题. 我们区间染色时把区间分成若干连续的颜色段,然后我们每次染色删除原来的颜色段插入新的颜色段. 我们发现我们的时间复杂度直接与我们要染色区 ...

  9. 【BZOJ 1647】[Usaco2007 Open]Fliptile 翻格子游戏 模拟、搜索

    第一步我们发现对于每一个格子,我们只有翻和不翻两种状态,我们发现一旦确定了第一行操作,那么第二行的操作也就随之确定了,因为第一行操作之后我们要想得到答案就得把第一行全部为0,那么第二行的每一个格子的操 ...

  10. 门户系统整合sso cookie共享及显示用户信息

    1.1 门户系统整合sso 在门户系统点击登录连接跳转到登录页面.登录成功后,跳转到门户系统的首页,在门户系统中需要从cookie中 把token取出来.所以必须在登录成功后把token写入cooki ...