wls 有三棵树,树上每个节点都有一个值 ai,现在有 2 种操作:

  1. 将一条链上的所有节点的值开根号向下取整;
  2. 求一条链上值的和;
    链的定义是两点之间的最短路。
    Input
    第一行两个数 n, q 分别代表树上点的数量和操作数量。
    第二行 n 个整数,第 i 个数代表第 i 个点的值 ai。
    接下来 n − 1 行, 每行两个整数 u, v 代表 u,v 之间有一条边。数据保证点两两联通。
    接下来 q 行,每行有个整数 op, u, v,op = 0 表示将 u, v 这条链上所有的点的值开根号向下取整,op = 1表示询问 u,v 这条链上的值的和。
    1 ≤ n, q ≤ 100, 000
    0 ≤ ai ≤ 1, 000, 000, 000
    Output
    对于每一组 op = 2 的询问,输出一行一个值表示答案。
    Sample Input
    4 4
    2 3 4 5
    1 2
    2 3
    2 4
    0 3 4
    0 1 3
    1 2 3
    1 1 4
    Sample Output
    2
    4

思路:

树链剖分裸题,

如何处理区间 开方,区间求和,可以看这个博客:

https://www.cnblogs.com/qieqiemin/p/11306562.html

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define chu(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
ll powmod(ll a, ll b, ll MOD) {ll ans = 1; while (b) {if (b % 2)ans = ans * a % MOD; a = a * a % MOD; b /= 2;} return ans;}
inline void getInt(int* p);
const int maxn = 100010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int n, m;
int root;
ll a[maxn];// 初始点权
ll wt[maxn];// 新建编号点权。
int cnt;// 编号用的变量
int top[maxn];// 所在重链的顶点编号
int id[maxn];//节点的新编号。
std::vector<int> son[maxn];
int SZ[maxn];// 子数大小
int wson[maxn];// 重儿子
int fa[maxn];// 父节点
int dep[maxn];// 节点的深度void dfs1(int id, int pre, int step) // 维护出sz,wson,fa,dep
{dep[id] = step;fa[id] = pre;SZ[id] = 1;int  maxson = -1;for (auto x : son[id]){if (x != pre){dfs1(x, id, step + 1);SZ[id] += SZ[x];if (SZ[x] > maxson){maxson = SZ[x];wson[id] = x;}}}}//处理出top[],wt[],id[]
void dfs2(int u,int topf)
{id[u] = ++cnt;wt[cnt]=a[u];top[u]=topf;if(!wson[u]) // 没儿子时直接结束{return ;}dfs2(wson[u],topf);// 先处理重儿子for(auto x:son[u]){if(x==wson[u]||x==fa[u])//只处理轻儿子{continue;}dfs2(x,x);// 每个轻儿子以自己为top}
}struct node
{int l,r;ll sum;ll laze;
}segment_tree[maxn<<2];void pushup(int rt)
{segment_tree[rt].sum=(segment_tree[rt<<1].sum+segment_tree[rt<<1|1].sum);
}
void build(int rt,int l,int r)
{segment_tree[rt].l=l;segment_tree[rt].r=r;segment_tree[rt].laze=0;if(l==r){segment_tree[rt].sum=wt[l];return;}int mid=(l+r)>>1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);pushup(rt);
}void update(int rt,int l,int r)
{if((segment_tree[rt].l>=l&&segment_tree[rt].r<=r)&&segment_tree[rt].sum==(segment_tree[rt].r-segment_tree[rt].l+1)){return ;}if(segment_tree[rt].l==segment_tree[rt].r){segment_tree[rt].sum=sqrt(segment_tree[rt].sum);return ;}int mid=(segment_tree[rt].l+segment_tree[rt].r)>>1;if(mid>=l){update(rt<<1,l,r);}if(mid<r){update(rt<<1|1,l,r);}pushup(rt);
}
ll query(int rt,int l,int r)
{if(segment_tree[rt].l>=l&&segment_tree[rt].r<=r){ll res=0ll;res+=segment_tree[rt].sum;return res;}int mid=(segment_tree[rt].l+segment_tree[rt].r)>>1;ll res=0ll;if(mid>=l){res+=query(rt<<1,l,r);}if(mid<r){res+=query(rt<<1|1,l,r);}return res;}void uprange(int x,int y)
{while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]])// 使x的top深度较大{swap(x,y);}update(1,id[top[x]],id[x]);// 处理x到top[x] 那段链x=fa[top[x]];// x向上爬到top[x]的父节点}if(dep[x]>dep[y])//使x的深度较小swap(x,y);update(1,id[x],id[y]);//更新x到y这段链,根据上面的处理,他们一定是在同一条链上
}ll qrange(int x,int y)
{ll ans=0ll;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]){swap(x,y);}ans+=query(1,id[top[x]],id[x]);x=fa[top[x]];}if(dep[x]>dep[y])swap(x,y);ans+=query(1,id[x],id[y]);return ans;
}
void upson(int x,ll val)
{update(1,id[x],id[x]+SZ[x]-1);//子树区间右端点为id[x]+siz[x]-1
}
ll qson(int x)
{ll res=0ll;res+=query(1,id[x],id[x]+SZ[x]-1);return res;
}
int main()
{
//    freopen("D:\\common_text\\code_stream\\in.txt","r",stdin);
//    freopen("D:\\common_text\\code_stream\\out.txt","w",stdout);gbtb;cin >> n >> m ;;repd(i, 1, n){cin >> a[i];}int u, v;repd(i, 2, n){cin >> u >> v;son[u].pb(v);son[v].pb(u);}root=1;dfs1(root,0,1);dfs2(root,root);build(1,1,n);int op,x,y,z;
//  操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z
//
//  操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和
//
//  操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z
//
//  操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和while(m--){cin>>op;if(op==0){cin>>x>>y;uprange(x,y);}else if(op==1){cin>>x>>y;cout<<qrange(x,y)<<endl;}}return 0;
}inline void getInt(int* p) {char ch;do {ch = getchar();} while (ch == ' ' || ch == '\n');if (ch == '-') {*p = -(getchar() - '0');while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 - ch + '0';}}else {*p = ch - '0';while ((ch = getchar()) >= '0' && ch <= '9') {*p = *p * 10 + ch - '0';}}
}

转载于:https://www.cnblogs.com/qieqiemin/p/11306597.html

Tree HDU - 6547 (树链剖分,线段树)相关推荐

  1. CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...

  2. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 1153  Solved: 421 [Submit][Sta ...

  4. CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...

  5. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  6. P2486 [SDOI2011]染色(树链剖分+线段树)

    题干描述 输入描述 输出格式 对于每个询问操作,输出一行答案. 输入输出样例 输入 #1 复制 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q ...

  7. BZOJ4127Abs——树链剖分+线段树

    题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...

  8. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  9. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

  10. YbtOJ-染色计划【树链剖分,线段树,tarjan】

    正题 题目大意 给出nnn个点的一棵树,每个点有个颜色aia_iai​,你每次可以选择一个颜色全部变成另一个颜色. 求最少多少次操作可以把一种颜色变成一个完整的连通块. 1≤k≤n≤2×1051\le ...

最新文章

  1. python 字符串前加u r b的意义
  2. Python 库安装问题-用pip安装pyHook3报错的两种常见问题和解决方法
  3. 将shell命令结果直接输出到HDFS上
  4. 数列分块入门 2(LibreOj-6278)
  5. C#比较时间方法(3种)
  6. 实验一 DOS命令解释程序的编写
  7. 【Docker】02 Docker安装
  8. 高等数学 常用数学公式
  9. KindEditor实现上传图片与回显
  10. 两波形相位差的计算值_连续模式PFC功率MOSFET电流有效值、平均值计算
  11. NLTK-006:分类文本(性别鉴定)
  12. HCIA-RoutingSwitching华为认证路由交换工程师(持续更新中2%)
  13. C++之char , signed char , unsigned char(转)
  14. pmp中ram和raci的区别_【PMP考前冲刺】知识点大全(六)
  15. unable to start ssh-agent service, error :1058 问题的解决方法
  16. Photoshop脚本 蒙尘与划痕滤镜的使用
  17. Div CSS网页布局对网站搜索引擎优化的影响
  18. 日记侠:如何在微信赚钱?你要学会细分思维!
  19. 全国计算机等级考试二级公共基础知识考试大纲(2022年版)
  20. Android 头像上传的实现

热门文章

  1. why I get 415 error for my http post Service request creation in JMeter
  2. Java Spring源码研究之BeanNameUrlHandlerMapping
  3. Cloud for Customer Mashup debug in IFrame
  4. 赵英时遥感原理分析和应用课件_细数5种停车场防砸车技术原理分析与应用
  5. wordpress漏洞上传php文件,WordPress wp-admin/includes/file.php任意文件上传漏洞
  6. 这样安装python库才是最正确的哦_这样安装 Python 库才是最正确的哦~
  7. iphone开蓝牙wifi上网慢_为啥我开锁总是比别人慢?
  8. 学习计算机游戏编程,在线游戏学编程,游戏编程汇总
  9. css两列等高,css 多列等高
  10. linux下本地的源的格式,[Linux]CentOS7搭建/配置:YUM仓库/源[本地源/HTTP源/自建源仓库...