[luogu P3384] [模板]树链剖分
[luogu P3384] [模板]树链剖分
题目描述
如题,已知一棵包含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取模)
输入输出样例
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
2 21
说明
时空限制:1s,128M
数据规模:
对于30%的数据: N \leq 10, M \leq 10N≤10,M≤10
对于70%的数据: N \leq {10}^3, M \leq {10}^3N≤103,M≤103
对于100%的数据: N \leq {10}^5, M \leq {10}^5N≤105,M≤105
( 其实,纯随机生成的树LCA+暴力是能过的,可是,你觉得可能是纯随机的么233 )
样例说明:
树的结构如下:

各个操作如下:

故输出应依次为2、21(重要的事情说三遍:记得取模)
树剖模板题啊。。。都快不会打树剖了。
显然,对于这种题目,就要将每一个点根据dfs序映射到线性表上,然后用线段树等维护。
对于1,2操作,就是树剖的基本修改-查询操作;
对于3,4操作,也就是在x的子树里修改查询。那么,一个子树内部的点在dfs序对应的线性表上是连续的,也就可以通过线段树维护了。
ps:树剖都是码农题。。不过打得倒还挺爽。
code:
%:pragma GCC optimize()
#include<bits/stdc++.h>
#define mid (((l)+(r))>>1)
#define amod(x,y) (((x)+=(y))%=T)
#define LL long long
#define IL inline
using namespace std;
;
],son[N<<];
int dep[N],fa[N],si[N],down[N],top[N],bel[N],idl[N],idr[N];
LL v[N],v0[N],a[N<<],t[N<<],T;
IL LL read() {
LL x=; char ch=getchar();
') ch=getchar();
+ch-',ch=getchar();
return x;
}
IL void add(int x,int y) {nxt[++tot]=lnk[x],lnk[x]=tot,son[tot]=y;}
IL void dfs(int x,int p) {
dep[x]=dep[p]+,fa[x]=p,si[x]=,down[x]=n+;
for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=p) {
dfs(son[j],x),si[x]+=si[son[j]];
down[x]=(si[down[x]]<si[son[j]])?son[j]:down[x];
}
}
IL void pre(int x,int p) {
idl[x]=++cloc;
) top[down[x]]=top[x],bel[down[x]]=bel[x],pre(down[x],x);
for (int j=lnk[x]; j; j=nxt[j]) if (son[j]!=p&&son[j]!=down[x]) {
top[son[j]]=son[j],bel[son[j]]=++chain,pre(son[j],x);
}
idr[x]=cloc;
}
IL LL am(LL x,LL y) {return (x+y)%T;}
IL ],a[c<<|]);}
IL void pushD(int c,int l,int r) {
amod(t[c<<],t[c]);
amod(t[c<<|],t[c]);
amod(a[c<<],t[c]*(LL)(mid-l+));
amod(a[c<<|],t[c]*(LL)(r-mid));
t[c]=;
}
IL void B(int c,int l,int r) {
if (l==r) {a[c]=v0[l]%T; return;}
B(c<<,l,mid),B(c<<|,mid+,r);
pushU(c);
}
IL void U(int c,int l,int r,LL v,int liml,int limr) {
)),pushD(c,l,r); return;}
pushD(c,l,r);
,l,mid,v,liml,limr);
|,mid+,r,v,liml,limr);
,l,mid,v,liml,mid),U(c<<|,mid+,r,v,mid+,limr);
pushU(c);
}
IL LL A(int c,int l,int r,int liml,int limr) {
if (l>=liml&&r<=limr) return a[c]%T;
pushD(c,l,r); LL ret=;
,l,mid,liml,limr));
|,mid+,r,liml,limr));
,l,mid,liml,mid)),amod(ret,A(c<<|,mid+,r,mid+,limr));
pushU(c); return ret%T;
}
IL void chain_U(int x,int y,LL v) {
while (bel[x]!=bel[y]) {
,,n,v,idl[top[x]],idl[x]),x=fa[top[x]];
,,n,v,idl[top[y]],idl[y]),y=fa[top[y]];
}
if (dep[x]>dep[y]) swap(x,y);
U(,,n,v,idl[x],idl[y]);
}
IL LL chain_A(int x,int y) {
LL ret=;
while (bel[x]!=bel[y]) {
,,n,idl[top[x]],idl[x])),x=fa[top[x]];
,,n,idl[top[y]],idl[y])),y=fa[top[y]];
}
if (dep[x]>dep[y]) swap(x,y);
amod(ret,A(,,n,idl[x],idl[y]));
return ret%T;
}
IL ,,n,v,idl[x],idr[x]);}
IL LL tree_A(,,n,idl[x],idr[x])%T;}
int main() {
n=read(),m=read(),r=read(),T=read();
; i<=n; i++) v[i]=read();
,x,y; i<n; i++) x=read(),y=read(),add(x,y),add(y,x);
dep[]=,si[n+]=,dfs(r,),pre(r,);
; i<=n; i++) v0[idl[i]]=v[i];
B(,,n);
for (int o,x,y,z; m; m--) {
o=read(),x=read(),y=(o<)?read():,z=(o&)?read():;
switch (o) {
:chain_U(x,y,(LL)z%T); break;
:printf("%lld\n",chain_A(x,y)%T); break;
:tree_U(x,(LL)z%T); break;
:printf("%lld\n",tree_A(x)%T); break;
}
}
;
}
[luogu P3384] [模板]树链剖分的更多相关文章
- 【Luogu P3384】树链剖分模板
树链剖分的基本思想是把一棵树剖分成若干条链,再利用线段树等数据结构维护相关数据,可以非常暴力优雅地解决很多问题. 树链剖分中的几个基本概念: 重儿子:对于当前节点的所有儿子中,子树大小最大的一个儿子就 ...
- [洛谷P3384] [模板] 树链剖分
题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...
- P3384 [模板] 树链剖分
#include <bits/stdc++.h> using namespace std; typedef long long ll; int n, m, rt, mod, cnt, to ...
- luoguP3384 [模板]树链剖分
luogu P3384 [模板]树链剖分 题目 #include<iostream> #include<cstdlib> #include<cstdio> #inc ...
- 模板 树链剖分BFS版本
//点和线段树都从1开始 //边使用vector vector<int> G[maxn]; ],num[maxn],iii[maxn],b[maxn],a[maxn],top[maxn], ...
- 『题解』洛谷P3384 【模板】树链剖分
Problem Portal Portal1: Luogu Description 如题,已知一棵包含\(N\)个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作\(1\): ...
- 树链剖分详解(洛谷模板 P3384)
洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...
- [note]树链剖分
树链剖分https://www.luogu.org/problemnew/show/P3384 概念 树链剖分,是一种将树剖分成多条不相交的链的算法,并通过其他的数据结构来维护这些链上的信息. 最简单 ...
- Luogu P3384 【【模板】树链剖分】
转载请注明出处,部分内容引自banananana大神的博客 ~~别说你不知道什么是树~~╮(─▽─)╭(帮你百度一下) 先来回顾两个问题:1,将树从x到y结点最短路径上所有节点的值都加上z 这也是个模 ...
随机推荐
- JSON数据展示神器:react-json-view(常用于后台网站)
一.react-json-view - npm 官方定义: RJV is a React component for displaying and editing javascript arrays ...
- 新加坡金融科技节 | 蚂蚁金服CTO程立:面向全球开放,与合作伙伴共赢
小蚂蚁说: 11月13日,在新加坡金融科技节上,蚂蚁金服CTO程立分别从TechFin.BASIC战略.SOFAStack全栈分布式体系以及全面开放等方面讲述蚂蚁金融科技. TechFin是一种“倒立 ...
- C#:导入Excel通用类(Xls格式)
PS:在CSV格式和XLSX格式中有写到通用调用的接口和引用的插件,所以在这个xls格式里面并没有那么详细,只是配上xls通用类. 一.引用插件NPOI.dll.NPOI.OOXML.dll.NPOI ...
- JAVA关于泛型的笔记
1.Java SE 5.0中增加泛型机制的主要原因是为了满足在1999年制定的最早的Java规范需求之一(JSR 14). 2.使用泛型机制编写的程序代码要比那些杂乱的使用Object变量,然后再进行 ...
- List<String> list=new ArrayList<String>(20);为什么要声明为List 而不是ArrayList<String>?
如何理解:List<String> list=new ArrayList<String>();为甚麼要声明为List 而不是ArrayList<String>? 在 ...
- vue2.0 axios交互
vue使用axios交互时候会出现的问题大致有三个: 1:本地调试跨域问题? 2:post请求,传参不成功,导致请求失败? 3:axios引用,在使用的组件里面引用 解决方案: 问题一:跨域? 解决本 ...
- (4)进程---daemon守护线程和join阻塞
join ()方法:主线程A中,创建了子线程B,并且在主线程A中调用了B.join(),那么,主线程A会在调用的地方等待,直到子线程B完成操作后,才可以接着往下执行,那么在调用这个线程时可以使用被调用 ...
- 响应式布局与bootstrap框架
原文 网页布局方式 1.固定宽度布局:为网页设置一个固定的宽度,通常以px做为长度单位,常见于PC端网页. 2.流式布局:为网页设置一个相对的宽度,通常以百分比做为长度单位. 3.栅格化布局:将网页宽 ...
- VS2008版本引入第三方dll无强签名
sn.exe 和ilasm.exe 是系统自带程序.如果显示无此命令,可以从“我的电脑”直接搜索. 将dll文件放入目录下,用VS开发人员命令执行以下命令即可.(以Interop.Scripting. ...
- Windows Phone 8 开发必备资源
一.MVVM框架推荐 1. MVVM-Light 这个框架是我最常用的MVVM框架之一,它比Prism更轻量级,但对于一般的小应用,功能足够. 官方网站:http://mvvmlight.codepl ...