Luogu - P3384 树链剖分 [挂模板专用]
题意:请码个树剖模板支持子树区间加/查询和路径加/查询
纯练手
盲敲技能++
以后网络赛复制模板速度++++
对链操作时注意方向
#include<bits/stdc++.h>
#define rep(i,j,k) for(register int i=j;i<=k;i++)
#define rrep(i,j,k) for(register int i=j;i>=k;i--)
#define println(a) printf("%lld\n",(ll)a)
using namespace std;
const int MAXN = 2e5+11;
typedef long long ll;
ll MOD;
ll read(){
ll x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int to[MAXN<<1],nxt[MAXN<<1],head[MAXN],tot; ll cost[MAXN<<1];
void add(int u,int v,ll w=0){
to[tot]=v;
cost[tot]=w;
nxt[tot]=head[u];
head[u]=tot++;
}
int size[MAXN],dfn[MAXN],dfned[MAXN],pre[MAXN],p[MAXN],son[MAXN],dep[MAXN],top[MAXN],CLOCK;
void init(){
memset(head,-1,sizeof head);
memset(son,0,sizeof son);
tot=CLOCK=0;
}
void dfs(int u,int fa,int d){
p[u]=fa; dep[u]=d; size[u]=1;
son[u]=top[u]=0;
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
if(v==fa) continue;
dfs(v,u,d+1);
size[u]+=size[v];
if(size[v]>size[son[u]]){
son[u]=v;
}
}
}
void dfs2(int u,int tp){
top[u]=tp;
dfn[u]=++CLOCK;
pre[CLOCK]=u;
if(son[u]) dfs2(son[u],tp);
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
if(v==p[u]||v==son[u]) continue;
dfs2(v,v);
}
dfned[u]=CLOCK;
}
int a[MAXN];
struct ST{
ll sum[MAXN<<2];
int lazy[MAXN<<2];
#define lc o<<1
#define rc o<<1|1
void pu(int o){
sum[o]=sum[lc]+sum[rc];
if(sum[o]>=MOD) sum[o]%=MOD;
}
void build(int o,int l,int r){
sum[o]=lazy[o]=0;
if(l==r){
sum[o]=a[pre[l]]; //!!
return;
}
int mid=l+r>>1;
build(lc,l,mid);
build(rc,mid+1,r);
pu(o);
}
void pd(int o,int l,int r){
if(lazy[o]){
int mid=l+r>>1;
sum[lc]+=(ll)(mid-l+1)*lazy[o];
sum[rc]+=(ll)(r-mid)*lazy[o];
if(sum[lc]>MOD) sum[lc]%=MOD;
if(sum[rc]>MOD) sum[rc]%=MOD;
lazy[lc]+=lazy[o];
lazy[rc]+=lazy[o];
lazy[o]=0;
}
}
void update(int o,int l,int r,int L,int R,ll v){
if(L<=l&&r<=R){
sum[o]+=(ll)(r-l+1)*v;
if(sum[o]>=MOD) sum[o]%=MOD;
lazy[o]+=v;
return;
}
pd(o,l,r);
int mid=l+r>>1;
if(L<=mid) update(lc,l,mid,L,R,v);
if(R>mid) update(rc,mid+1,r,L,R,v);
pu(o);
}
ll query(int o,int l,int r,int L,int R){
if(L<=l&&r<=R){
return sum[o];
}
pd(o,l,r);
int mid=l+r>>1;
ll ans=0;
if(L<=mid) ans+=query(lc,l,mid,L,R);
if(R>mid) ans+=query(rc,mid+1,r,L,R);
return ans>=MOD?ans%MOD:ans;
}
}st;
void solve(int u,int v,int val,int op){
ll ans=0;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
if(op==2) ans+=st.query(1,1,CLOCK,dfn[top[u]],dfn[u]);
if(op==2&&ans>=MOD) ans%=MOD;
else st.update(1,1,CLOCK,dfn[top[u]],dfn[u],val);
u=p[top[u]];
}
//same link
if(dep[u]<dep[v]) swap(u,v);
if(op==2) ans+=st.query(1,1,CLOCK,dfn[v],dfn[u]);//att
if(op==2&&ans>=MOD) ans%=MOD;
else st.update(1,1,CLOCK,dfn[v],dfn[u],val);
if(op==2) println(ans%MOD);
}
int main(){
int n,m,rt;
while(cin>>n>>m>>rt>>MOD){
init();
rep(i,1,n) a[i]=read();
rep(i,1,n-1){
int u=read();
int v=read();
add(u,v);
add(v,u);
}
dfs(rt,-1,1); dfs2(rt,rt);
st.build(1,1,CLOCK);
while(m--){
int op=read();
if(op==1){
int u=read();
int v=read();
ll val=read();
solve(u,v,val,op);
}else if(op==2){
int u=read();
int v=read();
solve(u,v,0,op);
}else if(op==3){
int x=read();
ll v=read();
int l=dfn[x],r=dfned[x];
st.update(1,1,CLOCK,l,r,v);
}else{
int x=read();
int l=dfn[x],r=dfned[x];
println(st.query(1,1,CLOCK,l,r)%MOD);
}
}
}
return 0;
}
Luogu - P3384 树链剖分 [挂模板专用]的更多相关文章
- 【luogu P3384 树链剖分】 模板
题目链接:https://www.luogu.org/problemnew/show/P3384 诶又给自己留了个坑..不想写线段树一大理由之前的模板变量名太长 #include <cstdio ...
- 洛谷 P3384 树链剖分(模板题)
题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...
- 树链剖分(模板) 洛谷P3384
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #d ...
- 洛谷P3384 树链剖分
如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x ...
- P3384——树链剖分&&模板
题目描述 链接 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: ...
- 洛谷树剖模板题 P3384 | 树链剖分
原题链接 对于以u为根的子树,后代节点的dfn显然比他的dfn大,我们可以记录一下回溯到u的dfn,显然这两个dfn构成了一个连续区间,代表u及u的子树 剩下的就和树剖一样了 #include< ...
- 【树链剖分/倍增模板】【洛谷】3398:仓鼠找sugar
P3398 仓鼠找sugar 题目描述 小仓鼠的和他的基(mei)友(zi)sugar住在地下洞穴中,每个节点的编号为1~n.地下洞穴是一个树形结构.这一天小仓鼠打算从从他的卧室(a)到餐厅(b),而 ...
- 洛谷 P3384树链剖分 题解
题面 挺好的一道树剖模板: 首先要学会最模板的树剖: 然后这道题要注意几个细节: 初始化时,seg[0]=1,seg[root]=1,top[root]=root,rev[1]=root; 在线段树上 ...
- 洛谷 [P3384] 树链剖分 模版
支持各种数据结构上树,注意取膜. #include <iostream> #include <cstring> #include <algorithm> #incl ...
随机推荐
- vim在linux下中如何设置显示行数
在.vimrc(或/etc/vimrc)文件中输入如下文本: set tabstop=4 set softtabstop=4 set shiftwidth=4 set noexpandtab ...
- centos7设置、查看、删除环境变量的方法
centos查看环境变量与设置环境变量在使用过程中很常见,本文整理了一些常用的与环境变量相关的命令,感兴趣的朋友可以参考下希望对你有所帮助 1. 显示环境变量HOME(红色部分代表要输入的命令,不要把 ...
- UVa 12099 The Bookcase (DP)
题意:有 n 本书,每本书有一个高度和宽度,然后让你制作一个3层的书架,可以放下所有的书,并且要高*宽尽量小. 析:先把所有的书按高度进行排序,然后dp[i][j][k] 表示 前 i 本书,第二 层 ...
- static 和final
1.static static关键字可以用来修饰类的变量,方法和内部类.static是静态的意思,也是全局的意思,它定义的东西属于全局,与类相关,不与具体实例相关.就是说它调用的时候,只是 ...
- 在 CentOS 上部署 Nginx 环境
这里的案例主要通过虚拟机( vmware workstation (14) )的方式安装 Center OS 到本地环境 资源下载: vmware workstation / CentOS 本次 ...
- 编写高质量代码改善C#程序的157个建议——建议65:总是处理未捕获的异常
建议65:总是处理未捕获的异常 处理为捕获的异常是每个应用程序具备的基本功能,C#在APPDomain提供了UnhandledException事件来接收未捕获到的异常的通知.常见的应用如下: sta ...
- loadrunner中对https证书的配置
1.准备好网站的证书,一般证书是cer格式: 2.因为loadrunner只支持pem格式的证书,所以要将证书转换格式,利用openssl工具:(或者直接让开发提供pem格式的证书) 3.得到pe ...
- [Delphi] Webbroker ISAPI 示例说明
新建Webbroker项目: 选择类型: 开始可以使用:Indy VCL Application 方便调试,完成后,再新建一个DLL 项目,引用业务单元. 示例代码如下: unit uDataMo ...
- Delphi xe5如何使用Bluestacks模拟器(用真机或者用猩猩,夜神模拟器,自带的不好用)
首先,关于这个模拟器问题比较纠结,这是一个关于adb的问题. Delphi XE5会自动识别模拟器和真机,但是你必须先打开模拟器在打开Delphi IDE(Delphi开发环境),否则还得麻烦一会儿. ...
- win10与子系统Ubuntu 相关配置
系统间 文件访问: 1. 在win10环境下访问Ubuntu文件系统的home目录:C:\Users\xxx\AppData\Local\Packages\CanonicalGroupLimited. ...