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版)的更多相关文章

  1. xcoj 1103 插线板(树链刨分求最大子段和)

    1103: 插线板 时间限制: 1 Sec  内存限制: 128 MB提交: 14  解决: 7 标签提交统计讨论版EditTestData 题目描述 从前有一堆古老的插线板,任意两个插线板之间只有一 ...

  2. bzoj 5210(树链刨分下做个dp)

    5210: 最大连通子块和 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 211  Solved: 65[Submit][Status][Discus ...

  3. hdu 5452(树链刨分)

    看到题目,想了挺长时间,发现不会,然后看着样子像是树上成段操作,所以查了下树链刨分,结果真的就是这个东西... Minimum Cut Time Limit: 3000/2000 MS (Java/O ...

  4. HDU - 3966 树链刨分

    题目传送门 操作就是询问某个点的值, 然后就是对一条路径上的值全部修改. 最基本的树刨题目了. 树刨的思想: 1. 对于每个点找到他的重儿子. void dfs1(int o, int u){ sz[ ...

  5. POJ 2763 Housewife Wind 树链拋分

    一.前言 这破题WA了一天,最后重构还是WA,最后通过POJ讨论版得到的数据显示,我看上去是把某个变量写错了..于是,还是低级错误背锅啊....代码能力有待进一步提升2333333 二.题意 某家庭主 ...

  6. HDU 3966 Aragorn's Story 树链拋分

    一.写在前面 终于开始开坑link-cut-tree这个了,对于网上找到的大佬的前进路线,进行了一番研发,发现实际上可以实现对于树链拋分的制作.经历了若干长时间之后终于打了出来(为什么每次学什么东西都 ...

  7. P3565 由简单的树形dp 引入 长链刨分

    这道题感觉不太行 因为自己没想出来. 先说一下暴力吧,取三个点 让两两之间的距离相等怎么做呢,看起来是很复杂的样子的,但是仔细观察发现 答案出自一个点的儿子之间 或者儿子和父亲之间. 暴力枚举三个点然 ...

  8. hdu 3804树链剖分+离线操作

    /* 树链刨分+离线操作 题意:给你一棵树,和询问x,y 从节点x--节点1的小于等于y的最大值. 解:先建一个空树,将树的边权值从小到大排序,将询问y按从小到大排序 对于每次询问y将小于等于y的边权 ...

  9. spoj 375 树链剖分模板

    /* 只是一道树链刨分的入门题,作为模板用. */ #include<stdio.h> #include<string.h> #include<iostream> ...

随机推荐

  1. Windows 使用 StarWind 创建的 Oracle RAC环境 异常关机之后的处理过程

    创建好了 虚拟机之后发现 偶尔会出现 蓝屏重启的现象, 这个时候 需要进行 异常处理 确定虚拟机已经开机之后 1. 打开iscsi的连接设备, 确认 iscsi的正常连接到虚拟机的 存储设备 注意 r ...

  2. Git从零开始(二)

    前面提交了一个test1.txt文件,接下来看看这个文件接下来的命运. 一.继续修改并提交 在test1.txt中修改后, git status 查看git的状态, 会提示我们文件test1.txt被 ...

  3. Android 四大组件和Intent

    一.Android有四大组件(component):Activity.Service.BroadcastReceiver.ContentProvider. 1.Activity 通过startActi ...

  4. Java设计模式之代理模式(静态代理和JDK、CGLib动态代理)以及应用场景

    我做了个例子 ,需要可以下载源码:代理模式 1.前言: Spring 的AOP 面向切面编程,是通过动态代理实现的, 由两部分组成:(a) 如果有接口的话 通过 JDK 接口级别的代理 (b) 如果没 ...

  5. Delphi字符串转日期,强大到窒息,VarToDateTime解决了困扰很久的小问题

    procedure THRForm.Button1Click(Sender: TObject); var D:TDateTime; s:string; begin D:=VarToDateTime(' ...

  6. Ubuntu17安装MySql5.7

    安装: sudo apt-get update sudo apt-get install mysql-server 配置远程访问: vi /etc/mysql/mysql.conf.d/mysqld. ...

  7. 服务端增加WCF服务全局异常处理机制

    服务端增加WCF服务全局异常处理机制,任一WCF服务或接口方式出现异常,将统一调用WCF_ExceptionHandler.ProvideFault方法,因此不需要每个方法使用try catch写法. ...

  8. MT【182】系数奇怪的二次函数

    设函数$f(x)=3ax^2-2(a+b)x+b,$其中$a>0,b\in R$证明:当$0\le x\le 1$时,$|f(x)|\le \max\{f(0),f(1)\}$ 分析:由$a&g ...

  9. [COGS 2551] 新型武器

    图片加载可能有点慢,请跳过题面先看题解,谢谢 这个题好多解法啊... 可以主席树,可以按深度将操作排序离线做 我这里是动态开点线段树,对每一个深度种一棵线段树,下标是节点的\(dfs\)序 然后这个做 ...

  10. tmux终端复用/tmate终端共享

    目录 tmux tmate tmux 一种终端复用工具,是终端中的窗口管理器.常见的一种用途是在关闭父shell时保持程序运行(常用于ssh访问断开连接后保持运行).linux上可通过包管理器进行安装 ...