题目链接:

[GXOI/GZOI2019]旧词

对于$k=1$的情况,可以参见[LNOI2014]LCA,将询问离线然后从$1$号点开始对这个点到根的路径链修改,每次询问就是对询问点到根路径链查询即可。

可以发现,如果一个点的贡献被记入答案,那么这个点到根的路径上所有点的贡献都会被记入答案。

那么对于$k>1$的情况,只要每次将路径上点$u$的权值都$+1$变成每次将路径上点$u$的权值都$+(dep[u]^k-(dep[u]-1)^k)$即可。

同样用线段树维护树剖序的区间权值和即可。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int mod=998244353;
int n,m,k;
int ans[50010];
int p[50010];
int son[50010];
int size[50010];
int f[50010];
int tot;
int head[50010];
int to[50010];
int nex[50010];
int dep[50010];
int top[50010];
int s[50010];
int q[50010];
int dfn;
int sum[400010];
int num[400010];
int tag[400010];
struct lty
{
int x,y,id;
}a[50010];
bool cmp(lty a,lty b)
{
return a.x<b.x;
}
int quick(int x,int y)
{
int res=1;
while(y)
{
if(y&1)
{
res=1ll*res*x%mod;
}
x=1ll*x*x%mod;
y>>=1;
}
return res;
}
void add_edge(int x,int y)
{
nex[++tot]=head[x];
head[x]=tot;
to[tot]=y;
}
int add(int x,int y)
{
if(x+y<mod)
{
return x+y;
}
else
{
return x+y-mod;
}
}
void dfs(int x)
{
size[x]=1;
for(int i=head[x];i;i=nex[i])
{
dep[to[i]]=dep[x]+1;
dfs(to[i]);
size[x]+=size[to[i]];
if(size[to[i]]>size[son[x]])
{
son[x]=to[i];
}
}
}
void dfs2(int x,int tp)
{
top[x]=tp;
s[x]=++dfn;
q[dfn]=x;
if(son[x])
{
dfs2(son[x],tp);
}
for(int i=head[x];i;i=nex[i])
{
if(to[i]!=son[x])
{
dfs2(to[i],to[i]);
}
}
}
void pushup(int rt)
{
sum[rt]=add(sum[rt<<1],sum[rt<<1|1]);
num[rt]=add(num[rt<<1],num[rt<<1|1]);
}
void pushdown(int rt)
{
if(tag[rt])
{
tag[rt<<1]=add(tag[rt],tag[rt<<1]);
tag[rt<<1|1]=add(tag[rt],tag[rt<<1|1]);
sum[rt<<1]=add(sum[rt<<1],1ll*tag[rt]*num[rt<<1]%mod);
sum[rt<<1|1]=add(sum[rt<<1|1],1ll*tag[rt]*num[rt<<1|1]%mod);
tag[rt]=0;
}
}
void build(int rt,int l,int r)
{
if(l==r)
{
num[rt]=p[dep[q[l]]];
return ;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void change(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
tag[rt]=add(tag[rt],1);
sum[rt]=add(sum[rt],num[rt]);
return ;
}
int mid=(l+r)>>1;
pushdown(rt);
if(L<=mid)
{
change(rt<<1,l,mid,L,R);
}
if(R>mid)
{
change(rt<<1|1,mid+1,r,L,R);
}
pushup(rt);
}
int query(int rt,int l,int r,int L,int R)
{
if(L<=l&&r<=R)
{
return sum[rt];
}
int mid=(l+r)>>1;
int res=0;
pushdown(rt);
if(L<=mid)
{
res=add(res,query(rt<<1,l,mid,L,R));
}
if(R>mid)
{
res=add(res,query(rt<<1|1,mid+1,r,L,R));
}
return res;
}
void modify(int x)
{
while(top[x]!=1)
{
change(1,1,n,s[top[x]],s[x]);
x=f[top[x]];
}
change(1,1,n,1,s[x]);
}
int ask(int x)
{
int res=0;
while(top[x]!=1)
{
res=add(res,query(1,1,n,s[top[x]],s[x]));
x=f[top[x]];
}
res=add(res,query(1,1,n,1,s[x]));
return res;
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
p[i]=(quick(i,k)-quick(i-1,k)+mod)%mod;
}
dep[1]=1;
for(int i=2;i<=n;i++)
{
scanf("%d",&f[i]);
add_edge(f[i],i);
}
dfs(1);
dfs2(1,1);
build(1,1,n);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
a[i].id=i;
}
sort(a+1,a+1+m,cmp);
int now=0;
for(int i=1;i<=m;i++)
{
while(now<a[i].x)
{
now++;
modify(now);
}
ans[a[i].id]=ask(a[i].y);
}
for(int i=1;i<=m;i++)
{
printf("%d\n",ans[i]);
}
}

[LOJ3088][GXOI/GZOI2019]旧词——树链剖分+线段树的更多相关文章

  1. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  2. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  3. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  4. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  5. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  6. HDU4897 (树链剖分+线段树)

    Problem Little Devil I (HDU4897) 题目大意 给定一棵树,每条边的颜色为黑或白,起始时均为白. 支持3种操作: 操作1:将a->b的路径中的所有边的颜色翻转. 操作 ...

  7. Aizu 2450 Do use segment tree 树链剖分+线段树

    Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...

  8. 【POJ3237】Tree(树链剖分+线段树)

    Description You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edg ...

  9. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  10. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

随机推荐

  1. Skyline Terra Explorer6.6弹出窗口实现复制功能

    前段时间继续下来的基于Skyline的B/S项目,是基于Terra Explorer6.6实现的.项目中涉及到基于三维模型查询设备编码等操作,从用户友好角度来讲,查询到的设备编码应该要支持复制,方便用 ...

  2. Android ListView的基本应用

    ListView可以说是Android原生开发最基本.最重要的控件之一,良好的使用ListView可以让自己的项目得到提高,下面是ListView最简单的应用方式 定义ListViewlist_vie ...

  3. OrmLite-更符合面向对象的数据库操作方式

    1. jar包下载 下载地址:http://ormlite.com/releases/,一般用core和android包即可. 如果使用的是android studio,也可以直接通过module s ...

  4. Java中单例模式的几种实现

    目录 懒汉式单例 简单版本 synchronized版本 双重检查(Double-Check)版本 volatile 饿汉式单例 实现1 其他实现方式 静态内部类-Effective Java 枚举- ...

  5. java或Jmeter实现两个日期相加减(2003-06-01-2003-05-01)

    在beanshell中写入如下代码, import java.io.FileInputStream; SimpleDateFormat myFormatter = new SimpleDateForm ...

  6. 服务消费者Feign和Ribbon的区别

    1.Ribbon通过注解@EnableEurekaClient/@EnableDiscoveryClient向服务中心注册:    PS:选用的注册中心是eureka,那么就推荐@EnableEure ...

  7. JProfiler的详细使用介绍

    转:https://blog.csdn.net/huangjin0507/article/details/52452946 下载软件 官网地址:http://www.ej-technologies.c ...

  8. FreeHttp (a fiddler add in to temper the http)

    introduction FreeHttp is a Fiddler plugin. With FreeHttp you can modify the request or response mess ...

  9. DAO层设计Junit测试

    DAO层的设计: 在实际的开发中有一种项目的程序组织架构方案叫做MVC模式. MVC模式就是按照程序的功能将它们分成三层,分别是Modle层 (模型层).View(显示层).Controller(控制 ...

  10. Java使用URL类下载的图片不完整

    问题 今天在使用URL类来下载网站中的图片的时候,出现了一个问题:下载的图片不完整,并且每次下载的图片大小也不是都相同,反正就是不完整. 问题代码如下: package cn.ganlixin.tes ...