luogu P3384 [模板]树链剖分 题目

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<algorithm>
#include<ctime>
#include<queue>
#define rg register
#define lst long long
#define N 100050
#define ls (now<<1)
#define rs (now<<1|1)
using namespace std; int n,m,root,p,cnt,ss,ans;
struct EDGE{
int to,nxt;
}edge[N<<];
struct TREE{
int l,r,siz,sum,lazy;
}ljl[N<<];
int first[N],v[N];
int fa[N],deep[N],son[N],size[N],top[N],num[N],vv[N]; inline int read()
{
rg int s=,m=;rg char ch=getchar();
while(ch!='-'&&(ch<''||ch>''))ch=getchar();
if(ch=='-')m=-,ch=getchar();
while(ch>=''&&ch<='')s=(s<<)+(s<<)+ch-'',ch=getchar();
return s*m;
} inline void add(rg int p,rg int q){edge[++cnt]=(EDGE){q,first[p]};first[p]=cnt;} void init()//输入点权和加边
{
n=read(),m=read(),root=read(),p=read();
for(rg int i=;i<=n;++i)v[i]=read(),size[i]=;
for(rg int i=;i<n;++i)
{
rg int p=read(),q=read();
add(p,q),add(q,p);
}
}
//______________________________________________输入,加边
void dfs_1(rg int now,rg int dep,rg int fm)//Dfs预处理 父亲节点 深度 子树大小
{
rg int kk=;//辅助找重儿子
fa[now]=fm,deep[now]=dep;//父亲,深度
for(rg int i=first[now];i;i=edge[i].nxt)//枚举儿子节点(边)
{
rg int qw=edge[i].to;//儿子
if(qw==fm)continue;
dfs_1(qw,dep+,now);//继续去找
size[now]+=size[qw];//处理子树大小
if(size[qw]>kk)kk=size[qw],son[now]=qw;//找重儿子
}
} void dfs_2(rg int now,rg int up)//找新的dfs序vv 处理now在dfs序中的位置num 所在重链的顶端
{
num[now]=++ss,top[now]=up,vv[ss]=v[now];//如上
if(son[now])dfs_2(son[now],top[now]);//先递归找重儿子
for(rg int i=first[now];i;i=edge[i].nxt)//再找其他儿子(边)
{
rg int qw=edge[i].to;
if(qw!=fa[now]&&qw!=son[now])//如上
dfs_2(qw,qw);
}
}
//__________________________________________________________dfs预处理
inline void Pushup(rg int now)//处理一下和
{
ljl[now].sum=(ljl[ls].sum+ljl[rs].sum+p)%p;
} inline void Pushdown(rg int now)//lazy标记下放
{
if(ljl[now].lazy)
{
ljl[ls].sum+=ljl[ls].siz*ljl[now].lazy;ljl[ls].sum%=p;
ljl[rs].sum+=ljl[rs].siz*ljl[now].lazy;ljl[rs].sum%=p;
ljl[ls].lazy+=ljl[now].lazy;ljl[ls].lazy%=p;
ljl[rs].lazy+=ljl[now].lazy;ljl[rs].lazy%=p;
ljl[now].lazy=;
}
} void build(rg int now,rg int ll,rg int rr)//建线段树
{
ljl[now]=(TREE){ll,rr,rr-ll+};
if(ll==rr){ljl[now].sum=vv[ll];return;}
rg int mid=(ll+rr)>>;
build(ls,ll,mid),build(rs,mid+,rr);
Pushup(now);
} void update(rg int now,rg int ll,rg int rr ,rg int xx)//区间ll到rr上加一个xx
{
if(ljl[now].l>=ll&&ljl[now].r<=rr)
{
ljl[now].sum+=ljl[now].siz*xx;
ljl[now].lazy+=xx;return;
}
Pushdown(now);
rg int mid=(ljl[now].l+ljl[now].r)/;
if(rr<=mid)update(ls,ll,rr,xx);
if(ll>mid)update(rs,ll,rr,xx);
if(ll<=mid&&rr>mid)
update(ls,ll,mid,xx),update(rs,mid+,rr,xx);
Pushup(now);
} int Query(rg int now,rg int ll,rg int rr)//求ll到rr区间的和
{
rg int s=;
if(ljl[now].l>=ll&&ljl[now].r<=rr)return ljl[now].sum;
Pushdown(now);
rg int mid=(ljl[now].l+ljl[now].r)>>;
if(rr<=mid)s+=Query(ls,ll,rr);
if(ll>mid) s+=Query(rs,ll,rr);
if(ll<=mid&&rr>mid)
s+=Query(ls,ll,mid)+Query(rs,mid+,rr);
Pushup(now),s%=p;
return s;
}
//__________________________________________________________线段树
inline void tree_work(rg int x,rg int y,rg int z,rg int op)
{
if(num[x]>num[y])swap(x,y);
if(!op)update(,num[x],num[y],z);
else ans+=Query(,num[x],num[y]);ans%=p;
} inline void tree_Work(rg int x,rg int y,rg int z,rg int op)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])swap(x,y);
tree_work(top[x],x,z,op);
x=fa[top[x]];
}
tree_work(x,y,z,op);
} inline void ANS()
{
for(rg int i=;i<=m;++i)
{
rg int type=read();ans=;
if(type==){rg int x=read(),y=read(),z=read(); tree_Work(x,y,z,);}
if(type==){rg int x=read(),y=read(); tree_Work(x,y,,);}
if(type==){rg int x=read(),z=read(); update(,num[x],num[x]+size[x]-,z);}
if(type==){rg int x=read(); ans=Query(,num[x],num[x]+size[x]-);}
if(type==||type==)printf("%d\n",ans);
}
} int main()
{
init();
dfs_1(root,,);
dfs_2(root,root);
build(,,ss);
ANS();
return ;
}

luoguP3384 [模板]树链剖分的更多相关文章

  1. [luogu P3384] [模板]树链剖分

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

  2. [洛谷P3384] [模板] 树链剖分

    题目传送门 显然是一道模板题. 然而索引出现了错误,狂wa不止. 感谢神犇Dr_J指正.%%%orz. 建线段树的时候,第44行. 把sum[p]=bv[pos[l]]%mod;打成了sum[p]=b ...

  3. 模板 树链剖分BFS版本

    //点和线段树都从1开始 //边使用vector vector<int> G[maxn]; ],num[maxn],iii[maxn],b[maxn],a[maxn],top[maxn], ...

  4. P3384 [模板] 树链剖分

    #include <bits/stdc++.h> using namespace std; typedef long long ll; int n, m, rt, mod, cnt, to ...

  5. 树链剖分详解(洛谷模板 P3384)

    洛谷·[模板]树链剖分 写在前面 首先,在学树链剖分之前最好先把 LCA.树形DP.DFS序 这三个知识点学了 emm还有必备的 链式前向星.线段树 也要先学了. 如果这三个知识点没掌握好的话,树链剖 ...

  6. 『题解』洛谷P3384 【模板】树链剖分

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

  7. P3384 【模板】树链剖分

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

  8. luogu3384 【模板】树链剖分

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

  9. 洛谷 P3384 【模板】树链剖分

    树链剖分 将一棵树的每个节点到它所有子节点中子树和(所包含的点的个数)最大的那个子节点的这条边标记为"重边". 将其他的边标记为"轻边". 若果一个非根节点的子 ...

随机推荐

  1. eclipse hibernate配置文件(*.hbm.xml)加上自动提示功能

    转自:https://blog.csdn.net/u012217085/article/details/17397843?utm_source=blogkpcl3 1. 标签:hibernate 在编 ...

  2. unity2017 光照与渲染(一)

    光照&渲染(基于unity2017.2.0) Custom Skybox 天空盒 最丰富的环境光 a. TextureShape 改成 Cube. b. 把图片直接丢给天空,就会自动生成材质. ...

  3. CCF CSP/CCSP报名费优惠的方法以及常见疑问

    目录 1. 本文地址 2. 认证作用 2.1. 高校认可 2.2. 赛事认可 2.3. 企业认可 3. 报名费价格及获取优惠的方法 3.1. CCF CSP 3.2. CCF CCSP 4. 语言与I ...

  4. Linux性能优化从入门到实战:05 CPU篇:硬中断、软中断

      软中断(softirq)会导致CPU 使用率升高   中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求.中断其实是一种异步的事件 ...

  5. python基础--内置函数map

    num_1=[1,2,10,5,3,7] # num_2=[] # for i in num_1: # num_2.append(i**2) # print(num_2) # def map_test ...

  6. [Tyvj1423]GF和猫咪的玩具(最短路)

    [Tyvj1423]GF和猫咪的玩具 题目描述 GF同学和猫咪得到了一个特别的玩具,这个玩具由n个金属环(编号为1---n),和m条绳索组成,每条绳索连接两个不同的金属环,并且长度相同.GF左手拿起金 ...

  7. P4206[NOI2005]聪聪与可可

    链接P4206 [NOI2005]聪聪与可可 类似于开车旅行,如果老鼠确定了那么猫的路线是确定的. 预处理\(g_{i,j}\)表示老鼠在\(i\)号点,猫的下一步方向,\(Bfs\)就行了 设\(f ...

  8. mpvue实现微信小程序(欢迎踩坑)

    最近刚使用mpvue完成了微信小程序的开发,写点东西,做个记录. 首先依旧是两个传送门: 微信小程序文档:[https://developers.weixin.qq.com/miniprogram/d ...

  9. VUE 生成二维码插件

    原文:https://www.jianshu.com/p/496fd1cbee8d npm install qrcodejs2 --save 页面中引入 dom 结构 JS 方法编写 export d ...

  10. 每次当浏览到网页,点击tab标签又回到顶部去了!

    通常tab的标签使用a链接,而a链接的href值为#,这是一个锚点的属性,因此他会跳转到网页的顶端.如果你的tab包含一个id=tab,也可以设置为href="#tab"这样他就会 ...