题目链接:

[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. Spring加载流程源码分析03【refresh】

      前面两篇文章分析了super(this)和setConfigLocations(configLocations)的源代码,本文来分析下refresh的源码, Spring加载流程源码分析01[su ...

  2. [转] 以后再有人问你selenium是什么,你就把这篇文章给他

    本文转自:https://blog.csdn.net/TestingGDR/article/details/81950593 写在最前面:目前自动化测试并不属于新鲜的事物,或者说自动化测试的各种方法论 ...

  3. Vue.js实现登录功能

    编写html,通过vue-resource.js库向后台提交数据 <!DOCTYPE html> <html lang="en"> <head> ...

  4. Pipenv项目化你的python应用

    目录 Pipenv 什么是pipenv 安装pipenv pipenv用法 使用pipenv开发项目 pipenv 结合 pyenv Pipenv 什么是pipenv Pipenv is a prod ...

  5. 视频文件列表hover添加视频播放按钮

    默认效果图: 鼠标hover效果: 代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8 ...

  6. 关于图片适配不同尺寸的image View(实战)

    分享人:广州华软 佐罗 一. 前言 在前端开发过程中,设计稿中往往只提供一张图片,但是app内需要用到的尺寸各种各样. 同时图片不仅是信息的直接表达,也会为网站起到美观点缀的作用,图片的变形.过分裁切 ...

  7. adb 查看 android手机的CPU架构

    adb shell cat  /proc/cpuinfo 当然要下载adb并配置好环境变量

  8. matlab中的实时音频

    音频系统工具箱™针对实时音频处理进行了优化.audioDeviceReader, audioDeviceWriter, audioPlayerRecorder, dsp.AudioFileReader ...

  9. <自动化测试方案_8>第八章、手机端UI自动化测试

    第八章.手机端UI自动化测试 (一)APP测试分类 1,原生APP:Native页面是使用原生系统内核的,相当于直接在系统上操作 2,H5APP:先调用系统的浏览器内核,相当于是在网页中进行操作,较原 ...

  10. ANT property三种使用方式

    方式一:引入*.properties文件 1.在cms.properties文件中定义属性 userName=admin 2.在build.xml中引入属性 <property file=&qu ...