博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【刷题】BZOJ 5293 [Bjoi2018]求和
阅读量:4994 次
发布时间:2019-06-12

本文共 5302 字,大约阅读时间需要 17 分钟。

Description

master 对树上的求和非常感兴趣。他生成了一棵有根树,并且希望多次询问这棵树上一段路径上所有节点深度的k

次方和,而且每次的k 可能是不同的。此处节点深度的定义是这个节点到根的路径上的边数。他把这个问题交给

了pupil,但pupil 并不会这么复杂的操作,你能帮他解决吗?

Input

第一行包含一个正整数n ,表示树的节点数。

之后n-1 行每行两个空格隔开的正整数i,j ,表示树上的一条连接点i 和点j 的边。

之后一行一个正整数m ,表示询问的数量。

之后每行三个空格隔开的正整数i,j,k ,表示询问从点i 到点j 的路径上所有节点深度的k 次方和。

由于这个结果可能非常大,输出其对998244353 取模的结果。

树的节点从1 开始标号,其中1 号节点为树的根。

Output

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

1≤n,m≤300000,1≤k≤50

Sample Input

5

1 2
1 3
2 4
2 5
2
1 4 5
5 4 45

Sample Output

33

503245989
说明
样例解释
以下用d(i) 表示第i 个节点的深度。
对于样例中的树,有d(1)=0,d(2)=1,d(3)=1,d(4)=2,d(5)=2。
因此第一个询问答案为(2^5 + 1^5 + 0^5) mod 998244353 = 33
第二个询问答案为(2^45 + 1^45 + 2^45) mod 998244353 = 503245989。

Solution

这题就一水题,指数小于等于50,直接对于每一个指数都维护树上两点权值和

开始写了一个树剖,交洛谷加O2过了,然后发现跑得有点慢,就又写了一个差分

这是差分的代码:

#include
#define ui unsigned int#define ll long long#define db double#define ld long double#define ull unsigned long longconst int MAXN=300000+10,Mod=998244353;int n,q,e,to[MAXN<<1],nex[MAXN<<1],beg[MAXN],Jie[MAXN][20],dep[MAXN];ll Sum[MAXN][51];template
inline void read(T &x){ T data=0,w=1; char ch=0; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')w=-1,ch=getchar(); while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar(); x=data*w;}template
inline void write(T x,char ch='\0'){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); if(ch!='\0')putchar(ch);}template
inline void chkmin(T &x,T y){x=(y
inline void chkmax(T &x,T y){x=(y>x?y:x);}template
inline T min(T x,T y){return x
inline T max(T x,T y){return x>y?x:y;}inline void insert(int x,int y){ to[++e]=y; nex[e]=beg[x]; beg[x]=e;}inline ll qexp(ll a,ll b){ ll res=1; while(b) { if(b&1)res=res*a%Mod; a=a*a%Mod; b>>=1; } return res;}inline void dfs1(int x,int f){ Jie[x][0]=f;dep[x]=dep[f]+1; for(register int i=beg[x];i;i=nex[i]) if(to[i]==f)continue; else dfs1(to[i],x); for(register int i=1;i<=50;++i)Sum[x][i]=qexp(dep[x],i);}inline void dfs2(int x){ for(register int i=1;i<=50;++i)(Sum[x][i]+=Sum[Jie[x][0]][i])%=Mod; for(register int i=beg[x];i;i=nex[i]) if(to[i]==Jie[x][0])continue; else dfs2(to[i]);}inline void init(){ dfs1(1,0); dfs2(1); for(register int j=1;j<19;++j) for(register int i=1;i<=n;++i)Jie[i][j]=Jie[Jie[i][j-1]][j-1];}inline int LCA(int u,int v){ if(dep[u]
dep[v]) for(register int i=19;i>=0;--i) if(dep[Jie[u][i]]>=dep[v])u=Jie[u][i]; if(u==v)return u; for(register int i=19;i>=0;--i) if(Jie[u][i]!=Jie[v][i])u=Jie[u][i],v=Jie[v][i]; return Jie[u][0];}int main(){ read(n); for(register int i=1;i

这是树剖的代码(开O2能过,不知道不开O2或者其他OJ上能不能过):

#include
#define ui unsigned int#define ll long long#define db double#define ld long double#define ull unsigned long longconst int MAXN=300000+10,Mod=998244353;int n,q,e,to[MAXN<<1],nex[MAXN<<1],beg[MAXN],st[MAXN],ed[MAXN],fa[MAXN],dep[MAXN],val[MAXN],hson[MAXN],size[MAXN],cnt,top[MAXN];#define Mid ((l+r)>>1)#define ls rt<<1#define rs rt<<1|1#define lson ls,l,Mid#define rson rs,Mid+1,rstruct Segment_Tree{ ll Sum[MAXN<<2][51]; inline ll qexp(ll a,ll b) { ll res=1; while(b) { if(b&1)res=res*a%Mod; a=a*a%Mod; b>>=1; } return res; } inline void PushUp(int rt) { for(register int i=1;i<=50;++i)Sum[rt][i]=(Sum[ls][i]+Sum[rs][i])%Mod; } inline void Build(int rt,int l,int r) { if(l==r) for(register int i=1;i<=50;++i)Sum[rt][i]=qexp(val[l],i); else { Build(lson);Build(rson); PushUp(rt); } } inline ll Query(int rt,int l,int r,int L,int R,int k) { if(L<=l&&r<=R)return Sum[rt][k]; else { ll res=0; if(L<=Mid)(res+=Query(lson,L,R,k))%=Mod; if(R>Mid)(res+=Query(rson,L,R,k))%=Mod; return res; } }};Segment_Tree T;#undef Mid#undef ls#undef rs#undef lson#undef rsontemplate
inline void read(T &x){ T data=0,w=1; char ch=0; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')w=-1,ch=getchar(); while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar(); x=data*w;}template
inline void write(T x,char ch='\0'){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); if(ch!='\0')putchar(ch);}template
inline void chkmin(T &x,T y){x=(y
inline void chkmax(T &x,T y){x=(y>x?y:x);}template
inline T min(T x,T y){return x
inline T max(T x,T y){return x>y?x:y;}inline void insert(int x,int y){ to[++e]=y; nex[e]=beg[x]; beg[x]=e;}inline void dfs1(int x,int f){ int res=0; dep[x]=dep[f]+1;size[x]=1;fa[x]=f; for(register int i=beg[x];i;i=nex[i]) if(to[i]==f)continue; else { dfs1(to[i],x); size[x]+=size[to[i]]; if(size[to[i]]>res)res=size[to[i]],hson[x]=to[i]; }}inline void dfs2(int x,int tp){ top[x]=tp;st[x]=++cnt;val[cnt]=dep[x]; if(hson[x])dfs2(hson[x],tp); for(register int i=beg[x];i;i=nex[i]) if(to[i]==fa[x]||to[i]==hson[x])continue; else dfs2(to[i],to[i]); ed[x]=cnt;}inline void init(){ dfs1(1,0); dfs2(1,1); T.Build(1,1,n);}inline ll Getans(int u,int v,int k){ ll res=0; while(top[u]!=top[v]) { if(dep[top[u]]

转载于:https://www.cnblogs.com/hongyj/p/8969557.html

你可能感兴趣的文章
BZOJ3569: DZY Loves Chinese II(线性基构造)
查看>>
Android系统源码下载及使用(Android 14到19源码)
查看>>
绑定dropdownlist
查看>>
[LeetCode] Sudoku Solver
查看>>
实验四
查看>>
Python Day04
查看>>
Android新增API之AudioEffect中文API与应用实例
查看>>
颜色空间RGB与HSV(HSL)的转换
查看>>
swift 用协议实现代理传值功能
查看>>
深入懂得android view 生命周期
查看>>
android.widget.FrameLayout$LayoutParams cannot be cast to android.widget.LinearLayout$LayoutParams
查看>>
Android 中 更新视图的函数ondraw() 和dispatchdraw()的区别
查看>>
《Java源码解析》之NIO的Selector机制(Part1:Selector.open())
查看>>
webpack安装问题
查看>>
Qt学习记录--Qt::CaseSensitive
查看>>
你的灯还亮着吗阅读笔记之一
查看>>
python介绍
查看>>
Unity-Editor按钮和菜单显示
查看>>
SharePoint InfoPath 保存无法发布问题
查看>>
word2vec:主要概念和流程
查看>>