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. 【转帖】 redis 命令 From https://www.cnblogs.com/zhouweidong/p/7550717.html

    redis命令详解   redis中添加key value元素:set key value;       获取元素:get key ;   redis中添加集合:lpush key value1 va ...

  2. 从0到1搭建基于Kafka、Flume和Hive的海量数据分析系统(一)数据收集应用

    大数据时代,一大技术特征是对海量数据采集.存储和分析的多组件解决方案.而其中对来自于传感器.APP的SDK和各类互联网应用的原生日志数据的采集存储则是基本中的基本.本系列文章将从0到1,概述一下搭建基 ...

  3. github如何添加新的分支

    需求:甲建立分支分给乙步骤:在甲创建的项目仓库里边点右上角的按钮 就可以通过名字搜索了. 在乙的右上角 再选中Repositories就可以看到所有的 存储库 了

  4. 【题解】 bzoj1207: [HNOI2004]打鼹鼠 (动态规划)

    bzoj1207,懒得复制,戳我戳我 Solution: 挺傻逼的一个\(dp\),直接推就好了 这题在bzoj上的数据有点问题,题目保证每个时间点不会出现在同一位置两个地鼠,然而他有= =(还浪费我 ...

  5. BZOJ 2427 [HAOI2010]软件安装 | 这道树形背包裸题严谨地证明了我的菜

    传送门 BZOJ 2427 题解 Tarjan把环缩成点,然后跑树形背包即可. 我用的树形背包是DFS序上搞的那种. 要注意dp数组初始化成-INF! 要注意dp顺推的时候也不要忘记看数组是否越界! ...

  6. 51nod1134——(最长上升子序列)

    给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10.   Input 第1行:1个 ...

  7. NO.6: 若不想编译器提供自动生成的函数,就应该明确拒绝

    1.为驳回编译器自动生成函数的技能,可把这些函数的声明放入private,如果是继承类型可把base class的这些函数声明private,可在编译期间得到警告

  8. CronExpression

    CronTrigger CronTriggers往往比SimpleTrigger更有用,如果您需要基于日历的概念,而非SimpleTrigger完全指定的时间间隔,复发的发射工作的时间表.CronTr ...

  9. 模拟QQ聊天与视频聊天同时进行-------java基础知识总结

    前言:多线程的知识 代码: package com.day13.math; /** * 类说明 :模拟QQ聊天与视频聊天同时进行 * @author 作者 : chenyanlong * @versi ...

  10. C语言复习---杨辉三角打印

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <math ...