树链刨分(class版)
class版树链剖(刨)分
感谢沙华大佬的赞助
其实没什么太大变化,就是用了几次一顿乱指。。。
CODE:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define ls (rt<<1)
#define rs (rt<<1|1)
#define mid ((l+r)>>1)
#define pushup(rt) t[rt].data=(t[ls].data+t[rs].data)%mod
#define N 100005
using namespace std;
int n,m,mod,tot,res;
int top[N],cnt,w[N],wt[N],head[N];
int fa[N],deep[N],idx[N],son[N],size[N];
class subdivision {
private:
struct edge {
int next,to;
}e[(N<<1)];
private:
struct segtree {
int data,left,right,tag;
inline int len() { return right - left + 1; }
}t[(N<<2)];
public:
inline void edge_build(int u,int v) {
e[++tot].to = v;
e[tot].next = head[u];
head[u] = tot;
return ;
}
public:
inline void tree_build(int rt , int l , int r){
t[rt].left = l;
t[rt].right = r;
t[rt].tag = 0;
if(l == r) {
t[rt].data = wt[l];
return ;
}
tree_build(ls,l,mid);
tree_build(rs,mid +1,r);
pushup(rt);
return ;
}
private:
inline void pushdown(int rt) {
t[ls].tag = (t[ls].tag + t[rt].tag) % mod;
t[rs].tag = (t[rs].tag + t[rt].tag) % mod;
t[ls].data = (t[ls].data + t[rt].tag * t[ls].len() ) % mod;
t[rs].data = (t[rs].data + t[rt].tag * t[rs].len() ) % mod;
t[rt].tag = 0;
return ;
}
public:
inline void update(int rt , int ll , int rr , int w) {
int l = t[rt].left;
int r = t[rt].right;
if(ll <= l && r <= rr) {
t[rt].tag += w;
t[rt].data = (t[rt].data + t[rt].len() * w) % mod;
return ;
}
if(t[rt].tag) pushdown(rt);
if(ll <= mid) update(ls,ll,rr,w);
if(rr > mid) update(rs,ll,rr,w);
pushup(rt);
return ;
}
public:
inline void query(int rt,int ll,int rr) {
int l = t[rt].left;
int r = t[rt].right;
if(ll <= l && r <= rr) {
res += t[rt].data;
return ;
}
if(t[rt].tag) pushdown(rt);
if(ll <= mid) query(ls,ll,rr);
if(rr > mid) query(rs,ll,rr);
return ;
}
public:
inline void dfs1(int now,int f,int dep) {
deep[now] = dep;
fa[now] = f;
size[now] = 1;
int maxson = -1;
for(int i = head[now] ; i ; i = e[i].next) {
int y = e[i].to;
if(y == f) continue;
dfs1(y , now , dep + 1);
size[now] += size[y];
if(size[y] > maxson) {
son[now] = y;
maxson = size[y];
}
}
return ;
}
public:
inline void dfs2(int now,int topf) {
idx[now] = ++cnt;
wt[cnt] = w[now];
top[now] = topf;
if(!son[now]) return ;
dfs2(son[now],topf);
for(int i = head[now] ; i ; i = e[i].next) {
int y = e[i].to;
if(y == fa[now] || y == son[now]) continue;
dfs2(y,y);
}
return ;
}
public:
inline int qrange(int x,int y) {
int ans = 0;
while(top[x] != top[y]) {
if(deep[top[x]] < deep[top[y]]) swap(x,y);
res = 0;
query(1 , idx[top[x]] , idx[x]);
ans = (ans + res) % mod;
x = fa[top[x]];
}
if(deep[x] > deep[y]) swap(x,y);
res = 0;
query(1 , idx[x] , idx[y]);
return (ans + res) % mod;
}
public:
inline void uprange(int x,int y,int k) {
k %= mod;
while(top[x] != top[y]) {
if(deep[top[x]] < deep[top[y]]) swap(x,y);
update(1 , idx[top[x]] , idx[x],k);
x = fa[top[x]];
}
if(deep[x] > deep[y]) swap(x,y);
update(1 , idx[x] , idx[y] , k);
return ;
}
};
subdivision *s;
int main(){
int root,a,b;
scanf("%d%d%d%d",&n,&m,&root,&mod);
for(int i = 1 ; i <= n ; ++i)
scanf("%d",&w[i]);
for(int i = 1 ; i < n ; ++i){
scanf("%d%d",&a,&b);
s->edge_build(a,b);
s->edge_build(b,a);
}
s->dfs1(root,0,1);
s->dfs2(root,root);
s->tree_build(1,1,n);
int k,x,y,z;
while(m--) {
scanf("%d%d",&k,&x);
if(k == 1) {
scanf("%d%d",&y,&z);
s->uprange(x,y,z);
}
if(k == 2) {
scanf("%d",&y);
printf("%d\n",s->qrange(x,y) );
}
if(k == 3) {
scanf("%d",&z);
s->update(1 , idx[x] , idx[x] + size[x]-1,z);
}
if(k == 4) {
res = 0;
s->query(1 , idx[x] , idx[x] + size[x]-1);
printf("%d\n",res % mod);
}
}
return 0;
}
树链刨分(class版)的更多相关文章
- xcoj 1103 插线板(树链刨分求最大子段和)
1103: 插线板 时间限制: 1 Sec 内存限制: 128 MB提交: 14 解决: 7 标签提交统计讨论版EditTestData 题目描述 从前有一堆古老的插线板,任意两个插线板之间只有一 ...
- bzoj 5210(树链刨分下做个dp)
5210: 最大连通子块和 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 211 Solved: 65[Submit][Status][Discus ...
- hdu 5452(树链刨分)
看到题目,想了挺长时间,发现不会,然后看着样子像是树上成段操作,所以查了下树链刨分,结果真的就是这个东西... Minimum Cut Time Limit: 3000/2000 MS (Java/O ...
- HDU - 3966 树链刨分
题目传送门 操作就是询问某个点的值, 然后就是对一条路径上的值全部修改. 最基本的树刨题目了. 树刨的思想: 1. 对于每个点找到他的重儿子. void dfs1(int o, int u){ sz[ ...
- POJ 2763 Housewife Wind 树链拋分
一.前言 这破题WA了一天,最后重构还是WA,最后通过POJ讨论版得到的数据显示,我看上去是把某个变量写错了..于是,还是低级错误背锅啊....代码能力有待进一步提升2333333 二.题意 某家庭主 ...
- HDU 3966 Aragorn's Story 树链拋分
一.写在前面 终于开始开坑link-cut-tree这个了,对于网上找到的大佬的前进路线,进行了一番研发,发现实际上可以实现对于树链拋分的制作.经历了若干长时间之后终于打了出来(为什么每次学什么东西都 ...
- P3565 由简单的树形dp 引入 长链刨分
这道题感觉不太行 因为自己没想出来. 先说一下暴力吧,取三个点 让两两之间的距离相等怎么做呢,看起来是很复杂的样子的,但是仔细观察发现 答案出自一个点的儿子之间 或者儿子和父亲之间. 暴力枚举三个点然 ...
- hdu 3804树链剖分+离线操作
/* 树链刨分+离线操作 题意:给你一棵树,和询问x,y 从节点x--节点1的小于等于y的最大值. 解:先建一个空树,将树的边权值从小到大排序,将询问y按从小到大排序 对于每次询问y将小于等于y的边权 ...
- spoj 375 树链剖分模板
/* 只是一道树链刨分的入门题,作为模板用. */ #include<stdio.h> #include<string.h> #include<iostream> ...
随机推荐
- shell 命令 if [ -d filename] 判断文件
作者:曹毅涵 [ -a FILE ] 如果 FILE 存在则为真. [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真. [ -c FILE ] 如果 FILE 存在且是一个字特殊 ...
- NOI备战总结ing……
持续做题ing…… 已完成: 树套树 点分治 博弈论 凸包 杜教筛 反演 FFT 数位DP DP专栏 网络流 数学专栏 正在进行中: waiting: SAM Kd-tree 矩阵树 分治 FWT B ...
- emWin 使用 GUIBuilder 放置标题 TEXT 注意
@2018-7-10 13:27:16 emWin 使用 GUIBuilder 放置标题 “Scroll Compressor”,有居中显示要求,为了内容可在程序中方便更改且能达到自适应,应将其属性大 ...
- 前端学习 -- Css -- 默认样式
浏览器为了在页面中没有样式时,也可以有一个比较好的显示效果, 所以为很多的元素都设置了一些默认的margin和padding,而它的这些默认样式,正常情况下我们是不需要使用的. 所以我们往往在编写样式 ...
- AdaBoost原理详解
写一点自己理解的AdaBoost,然后再贴上面试过程中被问到的相关问题.按照以下目录展开. 当然,也可以去我的博客上看 Boosting提升算法 AdaBoost 原理理解 实例 算法流程 公式推导 ...
- JSON.parseObject(String str)与JSONObject.parseObject(String str)的区别
一.首先来说说fastjson fastjson 是一个性能很好的 Java 语言实现的 JSON 解析器和生成器,来自阿里巴巴的工程师开发.其主要特点是: ① 快速:fastjson采用独创的算法, ...
- OOP的函数方法
<?php class Computer{ //我要创建一个构造方法 public function __construct(){ echo '我是比较先进的构造方法!'; //构造方法一般用于 ...
- CentOS 6.8下安装python的redis支持库
方法很简单,SSH登录下输入: pip install redis 或者 easy_install redis 如果上面的方法不行的话,就要尝试编译安装了 wget https://pypi.pyth ...
- BFC的个人理解
BFC是Block Formatting Context (块级格式化上下文)的缩写,是一个独立的渲染区域,这个东西的存在是为了隔绝一些内部子元素对外部元素的影响. 例如: 我们用overflow:h ...
- jQuery下ajax事件的简单分析
昨天写了一篇关于监视页面动态生成元素问题的文章,引起了一些小小的争议,不过我从中学到了很多.文章在这,<jQuery下实现等待指定元素加载完毕>当然 动态生成的节点元素 分很多种情况,这里 ...