[BJOI2018]求和(树链剖分)
题目描述
master 对树上的求和非常感兴趣。他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的 kkk 次方和,而且每次的 kkk 可能是不同的。此处节点深度的定义是这个节点到根的路径上的边数。他把这个问题交给了pupil,但pupil 并不会这么复杂的操作,你能帮他解决吗?
输入输出格式
输入格式:
第一行包含一个正整数 nnn ,表示树的节点数。
之后 n−1n-1n−1 行每行两个空格隔开的正整数 i,ji, ji,j ,表示树上的一条连接点 iii 和点 jjj 的边。
之后一行一个正整数 mmm ,表示询问的数量。
之后每行三个空格隔开的正整数 i,j,ki, j, ki,j,k ,表示询问从点 iii 到点 jjj 的路径上所有节点深度的 kkk 次方和。由于这个结果可能非常大,输出其对 998244353998244353998244353 取模的结果。
树的节点从 111 开始标号,其中 111 号节点为树的根。
输出格式:
对于每组数据输出一行一个正整数表示取模后的结果。
输入输出样例
说明
样例解释
以下用 d(i)d (i)d(i) 表示第 iii 个节点的深度。
对于样例中的树,有 d(1)=0,d(2)=1,d(3)=1,d(4)=2,d(5)=2d (1) = 0, d (2) = 1, d (3) = 1, d (4) = 2, d (5) = 2d(1)=0,d(2)=1,d(3)=1,d(4)=2,d(5)=2 。
因此第一个询问答案为 (25+15+05) mod 998244353=33(2^5 + 1^5 + 0^5)\ mod\ 998244353 = 33(25+15+05) mod 998244353=33 ,第二个询问答案为 (245+145+245) mod 998244353=503245989(2^{45} + 1^{45} + 2^{45})\ mod\ 998244353 = 503245989(245+145+245) mod 998244353=503245989 。
数据范围
对于 30%30\%30% 的数据, 1≤n,m≤1001 \leq n,m \leq 1001≤n,m≤100 。
对于 60%60\%60% 的数据, 1≤n,m≤10001 \leq n,m \leq 10001≤n,m≤1000 。
对于 100%100\%100% 的数据, 1≤n,m≤300000,1≤k≤501 \leq n,m \leq 300000, 1 \leq k \leq 501≤n,m≤300000,1≤k≤50 。
另外存在5个不计分的hack数据
提示
数据规模较大,请注意使用较快速的输入输出方式。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int N=;
const int mod=;
int n,m,dep[][N],fa[N],size[N],son[N],maxx,fid[N];
int l[N],tot,head[N*],num,top[N];
struct node{
int to,next;
}e[N*];
struct tr{
int sum[N*];
}t[];
int read()
{
int x=,w=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')w=-;ch=getchar();}
while(ch>=''&&ch<='')x=x*+ch-'',ch=getchar();
return x*w;
} void add(int from,int to)
{
num++;
e[num].to=to;
e[num].next=head[from];
head[from]=num;
} void dfs1(int x)
{
size[x]=;
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(!dep[][v]&&v!=)
{
dep[][v]=dep[][x]+;fa[v]=x;
maxx=max(maxx,dep[][v]);
dfs1(v);
size[x]+=size[v];
if(size[v]>size[son[x]])son[x]=v;
}
}
} void dfs2(int x,int tp)
{
l[x]=++tot;top[x]=tp;fid[tot]=x;
if(son[x])dfs2(son[x],tp);
for(int i=head[x];i;i=e[i].next)
{
int v=e[i].to;
if(v!=fa[x]&&v!=son[x])
dfs2(v,v);
}
} void init()
{
n=read();
for(int i=;i<n;i++)
{
int x=read(),y=read();
add(x,y);add(y,x);
}
dfs1();
dep[][]=;fa[]=;
dfs2(,);
} void build(int rt,int root,int left,int right)
{ if(left==right){
t[rt].sum[root]=dep[rt][fid[left]];
return ;
}
int mid=(left+right)>>;
build(rt,root<<,left,mid);
build(rt,root<<|,mid+,right);
t[rt].sum[root]=(ll)(t[rt].sum[root<<]+t[rt].sum[root<<|])%mod;
if(t[rt].sum[root]>=mod)t[rt].sum[root]-=mod;
} int query(int rt,int root,int left,int right,int L,int R)
{
if(left>R||right<L)return ;
if(L<=left&&right<=R)return t[rt].sum[root]%mod;
int mid=(left+right)>>;
ll a=,b=;
if(mid>=L)a=query(rt,root<<,left,mid,L,R)%mod;
if(mid<R) b=query(rt,root<<|,mid+,right,L,R)%mod;
return (a+b)%mod;
} int cal(int rt,int x,int y)
{
ll ans=;
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(dep[fx]<dep[fy]){swap(fx,fy);swap(x,y);}
ans+=query(rt,,,n,l[fx],l[x]);
ans%=mod;
x=fa[fx],fx=top[x];
}
if(l[x]>l[y])swap(x,y);
ans+=query(rt,,,n,l[x],l[y]);
ans%=mod;
return ans;
} void perp()
{
for(int i=;i<=;i++)
for(int j=;j<=n;j++)
{dep[i][j]=((ll)dep[i-][j]%mod*(ll)dep[][j]%mod)%mod;}
for(int i=;i<=;i++)
build(i,,,n);
} void solve()
{
m=read();
for(int i=;i<=m;i++)
{int x=read(),y=read(),k=read();
printf("%d\n",cal(k,x,y));}
} int main()
{
init();
perp();
solve();
return ;
}
[BJOI2018]求和(树链剖分)的更多相关文章
- 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释
P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...
- BZOJ 1036: [ZJOI2008]树的统计Count(树链剖分+单点更新+区间求和+区间求最大值)
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 题意:略. 题解:树链剖分模版,注意一些细节即可. #include <ios ...
- 树链剖分好(du)题(liu)选做
1.luogu P4315 月下"毛景树" 题目链接 前言: 这大概是本蒟蒻A掉的题里面码量最大的一道题了.我自认为码风比较紧凑,但还是写了175行. 从下午2点多调到晚上8点.中 ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- 树链剖分(+线段树)(codevs4633)
type node=^link; link=record des:longint; next:node; end; type seg=record z,y,lc,rc,toadd,sum:longin ...
- 【BZOJ-3589】动态树 树链剖分 + 线段树 + 线段覆盖(特殊的技巧)
3589: 动态树 Time Limit: 30 Sec Memory Limit: 1024 MBSubmit: 405 Solved: 137[Submit][Status][Discuss] ...
- BZOJ 1036 树的统计-树链剖分
[ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...
- 树分治&树链剖分相关题目讨论
预备知识 树分治,树链剖分 poj1741 •一棵有n个节点的树,节点之间的边有长度.方方方想知道,有多少个点对距离不超过m 题解 点分治模板题.详见我早上写的http://www.cnblogs ...
- 树链剖分||dfs序 各种题
1.[bzoj4034][HAOI2015]T2 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把 ...
- FZU 2082 过路费 (树链剖分 修改单边权)
题目链接:http://acm.fzu.edu.cn/problem.php?pid=2082 树链剖分模版题,求和,修改单边权. #include <iostream> #include ...
随机推荐
- html5plus 从相册选择图片后获取图片的大小
plus.gallery.pick(function (filePath) { plus.io.resolveLocalFileSystemURL(filePath, function (entry) ...
- 【原创】关于class.forname
连接数据库前都要调用一下class.forname("driverName");然后使用DriverMnager获取连接,这是为什么呢? 首先jdbc标准要求,每个驱动必须向Dri ...
- 3dmax实例教程-使用3ds Max 创建一个完整的场景
本篇教程讲述了利用3ds max创建一个完整的场景. 灵感来源:当我在遇到一些事情睡不着觉的时候我便在努力想象一些别的事情,于是我便想到了这个场景,其实对于我的这个角色我即没有参考图也没有草稿图,有的 ...
- 洛谷P2607 [ZJOI2008]骑士 基环树动归
Code: #include<algorithm> #include<cstdio> #include<algorithm> #include<cstring ...
- iOS开发——GCD总结
Grand Central Dispatch,简称GCD,在异步执行任务的技术之一. 一般将应用程序中记述的线程管理用的代码在系统级中实现,开发者只需要定义想执行的任务并追加到适当的Dispatch ...
- [SHOI2009]Booking 会场预约
题目:洛谷P2161. 题目大意:有一些操作,分为两种: A.增加一个从第l天到第r天的预约,并删除与这个预约冲突的其他预约,输出删除了多少个预约. B.输出当前有效预约个数. 两个预约冲突定义为两个 ...
- [Angular] Configure an Angular App at Compile Time with the Angular CLI
Compile time configuration options allow you to provide different kind of settings based on the envi ...
- github git.exe位置
C:\Users\yourname\AppData\Local\GitHub\PortableGit_69703d1db91577f4c666e767a6ca5ec50a48d243\bin\git. ...
- C++ 何时使用动态分配(即使用newkeyword)?何时使用指针?
动态分配 在你的问题里.你用了两种方式创建对象.这两种方式基本的不同在于对象的存储时间. 当运行Object myObject;这句代码时.它作为自己主动变量被创建,这意味着当对象出了作用域时也会自己 ...
- oracle新手随记10
1. unpivot注意点:select new_col from (select ename,job,to_char(sal) as sal,null as c from emp) ...