题目描述

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 号节点为树的根。

输出格式:

对于每组数据输出一行一个正整数表示取模后的结果。

输入输出样例

输入样例#1:
复制

5
1 2
1 3
2 4
2 5
2
1 4 5
5 4 45
输出样例#1: 复制

33
503245989

说明

样例解释

以下用 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数据

提示

数据规模较大,请注意使用较快速的输入输出方式。


先抱怨一波好吧,
  bjoi多么良心,出了那么多数据结构,mmp,再看看hnoi,woc,真的不要脸
  所以我这种菜鸡就只能打一打树剖这种傻逼题来泄愤了
 
题解:
 
  1)50次方,就是把每一个次方的值建一个线段树,后面就可以直接询问了
  2)取mod是一个很玄学的东西
  3)注意一下空间
  4)所有树剖题目都是一个思路,不难想但是难调
 

#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]求和(树链剖分)的更多相关文章

  1. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  2. BZOJ 1036: [ZJOI2008]树的统计Count(树链剖分+单点更新+区间求和+区间求最大值)

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 题意:略. 题解:树链剖分模版,注意一些细节即可. #include <ios ...

  3. 树链剖分好(du)题(liu)选做

    1.luogu P4315 月下"毛景树" 题目链接 前言: 这大概是本蒟蒻A掉的题里面码量最大的一道题了.我自认为码风比较紧凑,但还是写了175行. 从下午2点多调到晚上8点.中 ...

  4. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

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

    type node=^link; link=record des:longint; next:node; end; type seg=record z,y,lc,rc,toadd,sum:longin ...

  6. 【BZOJ-3589】动态树 树链剖分 + 线段树 + 线段覆盖(特殊的技巧)

    3589: 动态树 Time Limit: 30 Sec  Memory Limit: 1024 MBSubmit: 405  Solved: 137[Submit][Status][Discuss] ...

  7. BZOJ 1036 树的统计-树链剖分

    [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 12904 Solved: 5191[Submit][Status ...

  8. 树分治&树链剖分相关题目讨论

    预备知识 树分治,树链剖分   poj1741 •一棵有n个节点的树,节点之间的边有长度.方方方想知道,有多少个点对距离不超过m 题解 点分治模板题.详见我早上写的http://www.cnblogs ...

  9. 树链剖分||dfs序 各种题

    1.[bzoj4034][HAOI2015]T2 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把 ...

  10. FZU 2082 过路费 (树链剖分 修改单边权)

    题目链接:http://acm.fzu.edu.cn/problem.php?pid=2082 树链剖分模版题,求和,修改单边权. #include <iostream> #include ...

随机推荐

  1. html5plus 从相册选择图片后获取图片的大小

    plus.gallery.pick(function (filePath) { plus.io.resolveLocalFileSystemURL(filePath, function (entry) ...

  2. 【原创】关于class.forname

    连接数据库前都要调用一下class.forname("driverName");然后使用DriverMnager获取连接,这是为什么呢? 首先jdbc标准要求,每个驱动必须向Dri ...

  3. 3dmax实例教程-使用3ds Max 创建一个完整的场景

    本篇教程讲述了利用3ds max创建一个完整的场景. 灵感来源:当我在遇到一些事情睡不着觉的时候我便在努力想象一些别的事情,于是我便想到了这个场景,其实对于我的这个角色我即没有参考图也没有草稿图,有的 ...

  4. 洛谷P2607 [ZJOI2008]骑士 基环树动归

    Code: #include<algorithm> #include<cstdio> #include<algorithm> #include<cstring ...

  5. iOS开发——GCD总结

    Grand Central Dispatch,简称GCD,在异步执行任务的技术之一. 一般将应用程序中记述的线程管理用的代码在系统级中实现,开发者只需要定义想执行的任务并追加到适当的Dispatch ...

  6. [SHOI2009]Booking 会场预约

    题目:洛谷P2161. 题目大意:有一些操作,分为两种: A.增加一个从第l天到第r天的预约,并删除与这个预约冲突的其他预约,输出删除了多少个预约. B.输出当前有效预约个数. 两个预约冲突定义为两个 ...

  7. [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 ...

  8. github git.exe位置

    C:\Users\yourname\AppData\Local\GitHub\PortableGit_69703d1db91577f4c666e767a6ca5ec50a48d243\bin\git. ...

  9. C++ 何时使用动态分配(即使用newkeyword)?何时使用指针?

    动态分配 在你的问题里.你用了两种方式创建对象.这两种方式基本的不同在于对象的存储时间. 当运行Object myObject;这句代码时.它作为自己主动变量被创建,这意味着当对象出了作用域时也会自己 ...

  10. oracle新手随记10

    1. unpivot注意点:select new_col from (select ename,job,to_char(sal) as sal,null as c from emp)         ...