热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Luogu3384【模板】树链剖分

题目描述如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:

题目描述

如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:

操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z

操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和

操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z

操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和

输入输出格式

输入格式:

 

第一行包含4个正整数N、M、R、P,分别表示树的结点个数、操作个数、根节点序号和取模数(即所有的输出结果均对此取模)。

接下来一行包含N个非负整数,分别依次表示各个节点上初始的数值。

接下来N-1行每行包含两个整数x、y,表示点x和点y之间连有一条边(保证无环且连通)

接下来M行每行包含若干个正整数,每行表示一个操作,格式如下:

操作1: 1 x y z

操作2: 2 x y

操作3: 3 x z

操作4: 4 x

 

输出格式:

 

输出包含若干行,分别依次表示每个操作2或操作4所得的结果(对P取模)

 

输入输出样例

输入样例#1: 复制

5 5 2 24
7 3 7 8 0
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3

输出样例#1: 复制

2
21

说明

时空限制:1s,128M

数据规模:

对于30%的数据: N≤10,M≤10 N \leq 10, M \leq 10 N10,M10

对于70%的数据: N≤103,M≤103 N \leq {10}^3, M \leq {10}^3 N103,M103

对于100%的数据: N≤105,M≤105 N \leq {10}^5, M \leq {10}^5 N105,M105

( 其实,纯随机生成的树LCA+暴力是能过的,可是,你觉得可能是纯随机的么233 )

样例说明:

树的结构如下:

各个操作如下:

故输出应依次为2、21(重要的事情说三遍:记得取模)

 

 解题思路:

  裸的树链剖分的模板。。。

推荐写法:

#include
using namespace std;
#define re register int
#define ll long long
#define INF 0x3f3f3f3f
#define maxn 100009
#define maxm
inline ll read()
{ll x
&#61;0,f&#61;1;char ch&#61;getchar();while(ch<&#39;0&#39;||ch>&#39;9&#39;){if(ch&#61;&#61;&#39;-&#39;)f&#61;-1;ch&#61;getchar();}while(ch>&#61;&#39;0&#39;&&ch<&#61;&#39;9&#39;){x&#61;(x<<1)&#43;(x<<3)&#43;(ll)(ch-&#39;0&#39;);ch&#61;getchar();}return x*f;
}
int id[maxn],rk[maxn],top[maxn],son[maxn],size[maxn],depth[maxn],fa[maxn];
int head[maxn],val[maxn],sum[maxn<<2],add[maxn<<2];
int n,m,k,ans,tot,cnt,root,base;
struct edge
{
int to,nxt;
}p[maxn
<<1];
#define ls(x) x<<1
#define rs(x) x<<1|1
void add_edge(re x,re y)
{p[
&#43;&#43;cnt]&#61;{y,head[x]},head[x]&#61;cnt;
}
void dfs1(int u,int father)
{depth[u]
&#61;depth[father]&#43;1,fa[u]&#61;father,size[u]&#61;1;for(int i&#61;head[u];i;i&#61;p[i].nxt){int v&#61;p[i].to;if(v&#61;&#61;father) continue;dfs1(v,u);size[u]&#43;&#61;size[v];if(size[v]>size[son[u]])son[u]&#61;v;}
}
void dfs2(int u,int father)
{top[u]
&#61;father,id[u]&#61;&#43;&#43;tot,rk[tot]&#61;u;if(!son[u]) return ;dfs2(son[u],father);for(int i&#61;head[u];i;i&#61;p[i].nxt){int v&#61;p[i].to;if(v!&#61;son[u]&&v!&#61;fa[u])dfs2(v,v); }
}
int mod(int x)
{
return x>&#61;base?x%base:x;
}
void push_up(int x)
{sum[x]
&#61;sum[ls(x)]&#43;sum[rs(x)];sum[x]&#61;mod(sum[x]);
}
void built(int x,int l,int r)
{
if(l&#61;&#61;r){sum[x]&#61;val[rk[l]];return ;}int mid&#61;(l&#43;r)>>1;built(ls(x),l,mid);built(rs(x),mid&#43;1,r);push_up(x);
}
void pass(int x,int l,int r,int k)
{add[x]
&#43;&#61;k,add[x]&#61;mod(add[x]);sum[x]&#43;&#61;(r-l&#43;1)*k,sum[x]&#61;mod(sum[x]);
}
void push_down(int x,int l,int r)
{
if(!add[x]) return ;int mid&#61;(l&#43;r)>>1;pass(ls(x),l,mid,add[x]);pass(rs(x),mid&#43;1,r,add[x]);add[x]&#61;0;
}
int Ask(int x,int l,int r,int nl,int nr)
{
int res&#61;0;if(nl<&#61;l&&r<&#61;nr)return sum[x];push_down(x,l,r);int mid&#61;(l&#43;r)>>1;if(nl<&#61;mid)res&#43;&#61;Ask(ls(x),l,mid,nl,nr),res&#61;mod(res);if(mid<nr)res&#43;&#61;Ask(rs(x),mid&#43;1,r,nl,nr),res&#61;mod(res);push_up(x);return res;
}
void Add(int x,int l,int r,int nl,int nr,int k)
{
if(nl<&#61;l&&r<&#61;nr){add[x]&#43;&#61;k,add[x]&#61;mod(add[x]);sum[x]&#43;&#61;(r-l&#43;1)*k,sum[x]&#61;mod(sum[x]);return ;}push_down(x,l,r);int mid&#61;(l&#43;r)>>1;if(nl<&#61;mid)Add(ls(x),l,mid,nl,nr,k);if(mid<nr)Add(rs(x),mid&#43;1,r,nl,nr,k);push_up(x);
}
void Work1(int x,int y,int z)
{
int fx&#61;top[x],fy&#61;top[y];while(fx!&#61;fy){if(depth[fx]>depth[fy])swap(x,y),swap(fx,fy);Add(1,1,tot,id[fy],id[y],z);y&#61;fa[fy],fy&#61;top[y];}if(id[x]>id[y])swap(x,y);Add(1,1,tot,id[x],id[y],z);
}
int Work2(int x,int y)
{
int res&#61;0,fx&#61;top[x],fy&#61;top[y];while(fx!&#61;fy){if(depth[fx]>depth[fy]) swap(x,y),swap(fx,fy);res&#43;&#61;Ask(1,1,tot,id[fy],id[y]),res&#61;mod(res);y&#61;fa[fy],fy&#61;top[y];}if(id[x]>id[y]) swap(x,y);res&#43;&#61;Ask(1,1,tot,id[x],id[y]),res&#61;mod(res);
}
int main()
{
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);n&#61;read(),m&#61;read(),root&#61;read(),base&#61;read();for(re i&#61;1;i<&#61;n;i&#43;&#43;)val[i]&#61;read();for(re i&#61;1;i){re x&#61;read(),y&#61;read();add_edge(x,y),add_edge(y,x);}dfs1(root,root),dfs2(root,root);built(1,1,tot);for(re i&#61;1;i<&#61;m;i&#43;&#43;) {re opt&#61;read(),x,y,z;if(opt&#61;&#61;1){x&#61;read(),y&#61;read(),z&#61;read();Work1(x,y,z);}if(opt&#61;&#61;2){x&#61;read(),y&#61;read();printf("%d\n",Work2(x,y));}if(opt&#61;&#61;3){x&#61;read(),z&#61;read();Add(1,1,tot,id[x],id[x]&#43;size[x]-1,z);}if(opt&#61;&#61;4){x&#61;read();printf("%d\n",Ask(1,1,tot,id[x],id[x]&#43;size[x]-1));}}fclose(stdin);fclose(stdout);return 0;
}

 

 

 

#include
using namespace std;
#define re register int
#define ll long long
#define INF 0x3f3f3f3f
#define maxn 100009
#define maxm
#define ls(x) x<<1
#define rs(x) x<<1|1
inline ll read()
{ll x
&#61;0,f&#61;1;char ch&#61;getchar();while(ch<&#39;0&#39;||ch>&#39;9&#39;){if(ch&#61;&#61;&#39;-&#39;)f&#61;-1;ch&#61;getchar();}while(ch>&#61;&#39;0&#39;&&ch<&#61;&#39;9&#39;){x&#61;(x<<1)&#43;(x<<3)&#43;(ll)(ch-&#39;0&#39;);ch&#61;getchar();}return x*f;
}
ll
base;
int n,m,k,ans,tot,cnt,root;
struct edge
{
int to,nxt;
}p[maxn
<<1];
int head[maxn],id[maxn],fa[maxn],depth[maxn],size[maxn],son[maxn],rk[maxn],top[maxn];
ll sum[maxn
<<2],add[maxn<<2],val[maxn];void add_edge(int x,int y)
{p[
&#43;&#43;cnt].to&#61;y,p[cnt].nxt&#61;head[x],head[x]&#61;cnt;
}
void dfs1(int u,int father)
{depth[u]
&#61;depth[father]&#43;1,size[u]&#61;1,fa[u]&#61;father;for(int i&#61;head[u];i;i&#61;p[i].nxt){int v&#61;p[i].to;if(v&#61;&#61;father) continue;dfs1(v,u); size[u]&#43;&#61;size[v];if(size[v]>size[son[u]])son[u]&#61;v;}
}
void dfs2(int u,int father)
{top[u]
&#61;father;id[u]&#61;&#43;&#43;tot;rk[tot]&#61;u;if(!son[u])return ;dfs2(son[u],father);for(int i&#61;head[u];i;i&#61;p[i].nxt){int v&#61;p[i].to;if(v!&#61;son[u]&&v!&#61;fa[u])dfs2(v,v);}
}
void push_up(int x)
{sum[x]
&#61;(sum[ls(x)]&#43;sum[rs(x)])%base;
}
void built(int x,int l,int r)
{
if(l&#61;&#61;r){sum[x]&#61;val[rk[l]];return ;}int mid&#61;(l&#43;r)>>1;built(ls(x),l,mid);built(rs(x),mid&#43;1,r);push_up(x);
}
void pass(int x,int l,int r,ll k)
{add[x]
&#43;&#61;k,add[x]%&#61;base;sum[x]&#43;&#61;(r-l&#43;1)*k,sum[x]%&#61;base;
}
void push_down(int x,int l,int r)
{
if(!add[x]) return ;int mid&#61;(l&#43;r)>>1;pass(ls(x),l,mid,add[x]);pass(rs(x),mid&#43;1,r,add[x]);add[x]&#61;0;
}ll Query(
int x,int l,int r,int nl,int nr)
{ll res
&#61;0;if(nl<&#61;l&&r<&#61;nr)return sum[x];push_down(x,l,r);int mid&#61;(l&#43;r)>>1;if(nl<&#61;mid)res&#43;&#61;Query(ls(x),l,mid,nl,nr),res%&#61;base;if(mid<nr)res&#43;&#61;Query(rs(x),mid&#43;1,r,nl,nr),res%&#61;base;push_up(x);return res%base;
}
void Add(int x,int l,int r,int nl,int nr,ll k)
{
if(nl<&#61;l&&r<&#61;nr){add[x]&#43;&#61;k,add[x]%&#61;base;sum[x]&#43;&#61;(r-l&#43;1)*k,sum[x]%&#61;base;return ;}push_down(x,l,r);int mid&#61;(l&#43;r)>>1;if(nl<&#61;mid)Add(ls(x),l,mid,nl,nr,k);if(mid<nr)Add(rs(x),mid&#43;1,r,nl,nr,k);push_up(x);
}
void Work1(int x,int y,ll z)
{
int fx&#61;top[x],fy&#61;top[y];while(fx!&#61;fy){if(depth[fx]>&#61;depth[fy]){Add(1,1,tot,id[fx],id[x],z);x&#61;fa[fx],fx&#61;top[x];}else{Add(1,1,tot,id[fy],id[y],z);y&#61;fa[fy],fy&#61;top[y];}}if(id[x]<&#61;id[y])Add(1,1,tot,id[x],id[y],z);elseAdd(1,1,tot,id[y],id[x],z);
}ll Work2(
int x,int y)
{ll ans
&#61;0;int fx&#61;top[x],fy&#61;top[y];while(fx!&#61;fy){if(depth[fx]>&#61;depth[fy]){ans&#43;&#61;Query(1,1,tot,id[fx],id[x]);x&#61;fa[fx];fx&#61;top[x];}else{ans&#43;&#61;Query(1,1,tot,id[fy],id[y]);y&#61;fa[fy];fy&#61;top[y];}}if(id[x]<&#61;id[y])ans&#43;&#61;Query(1,1,tot,id[x],id[y]),ans%&#61;base;elseans&#43;&#61;Query(1,1,tot,id[y],id[x]),ans%&#61;base;return ans%base;
}
void Work3(int x,int y)
{Add(
1,1,tot,id[x],id[x]&#43;size[x]-1,y);
}ll Work4(
int x)
{ll res
&#61;Query(1,1,tot,id[x],id[x]&#43;size[x]-1);return res%base;
}
int main()
{freopen(
"1.in","r",stdin);freopen("1.out","w",stdout);n&#61;read(),m&#61;read(),root&#61;read(),base&#61;read();for(int i&#61;1;i<&#61;n;i&#43;&#43;)val[i]&#61;read()%base;for(int i&#61;1;i){int x&#61;read(),y&#61;read();add_edge(x,y),add_edge(y,x);}dfs1(root,root),dfs2(root,root);built(1,1,tot);for(int i&#61;1;i<&#61;m;i&#43;&#43;){int opt&#61;read(),x,y;ll z;if(opt&#61;&#61;1){x&#61;read(),y&#61;read(),z&#61;read();Work1(x,y,z); }if(opt&#61;&#61;2){x&#61;read(),y&#61;read();printf("%lld\n",Work2(x,y));}if(opt&#61;&#61;3){x&#61;read(),z&#61;read();Work3(x,z);}if(opt&#61;&#61;4){x&#61;read();printf("%lld\n",Work4(x));}}fclose(stdin);fclose(stdout);return 0;
}

 

转:https://www.cnblogs.com/Dxy0310/p/9873401.html



推荐阅读
  • 题面传送门Solution看到什么最大值最小肯定二分啊。check直接跑一个二分图匹配就好了。orzztl!!!代码实现*mail:mle ... [详细]
  • 本文主要介绍了gym102222KVertex Covers(高维前缀和,meet in the middle)相关的知识,包括题意、思路和解题代码。题目给定一张n点m边的图,点带点权,定义点覆盖的权值为点权之积,要求所有点覆盖的权值之和膜qn小于等于36。文章详细介绍了解题思路,通过将图分成两个点数接近的点集L和R,并分别枚举子集S和T,判断S和T能否覆盖所有内部的边。文章还提到了使用位运算加速判断覆盖和推导T'的方法。最后给出了解题的代码。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 796.[APIO2012]派遣在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿。在这个帮派里,有一名忍者被称之为Master。 ... [详细]
  • 题目描述Takuru是一名情报强者,所以他想利用他强大的情报搜集能力来当中间商赚差价。Takuru的计划是让Hinae帮他去市场上买一个商品,然后再以另一个价格卖掉它。Takur ... [详细]
  • DescriptionclickmeSolution套路的状压期望DP题。。。考虑倒退期望:设fi,jrolepresentationstyleposi ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • 本文由编程笔记#小编整理,主要介绍了关于数论相关的知识,包括数论的算法和百度百科的链接。文章还介绍了欧几里得算法、辗转相除法、gcd、lcm和扩展欧几里得算法的使用方法。此外,文章还提到了数论在求解不定方程、模线性方程和乘法逆元方面的应用。摘要长度:184字。 ... [详细]
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
  • java io换行符_Java IO:为什么从stdin读取时,换行符的数字表示出现在控制台上?...
    只是为了更好地理解我在讲座中听到的内容(关于Java输入和输出流),我自己做了这个小程序:publicstaticvoidmain(String[]args)thro ... [详细]
  • P2765魔术球问题这道题的思路实在是太罕见了,所以发一篇blog从某一新放入的球开始看起1.放入原来的柱子上2.放入新的柱子并将每个点进行拆点࿰ ... [详细]
  • P113:集成日志组件 logback 2彩色日志
    第二步,将控制台的日志改成彩色日志,便于查看修改logback.xml文件。 ... [详细]
  • 学习mybatis的基础知识:mybatis入门教程(二)
    2019独角兽企业重金招聘Python工程师标准2.3MyBatisprintsql在log4j.properties配置文件中添加如下配置,让mybatis打 ... [详细]
author-avatar
真真贱贱_474
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有