题目链接:点击查看

题目大意:给出一棵由n个点组成的树,每个点都有一个权值,接下来有k次操作,每次操作分为下面几种类型:

  1. I u v x:将u-v这条路径上的所有点权值加上x
  2. D u v x:将u-v这条路径上的所有点权值减去x
  3. Q x:查询点x的权值

题目分析:因为又涉及到了树上路径的问题,这个题涉及到的是路径上的点权修改,很容易和线段树的区间修改联想到一起,所以我们还是先剖一下,剖完之后直接建立线段树,然后这个问题就转换成了最简单的sum线段树的维护了,也是好久没写区间更新的线段树了,练习了一下lazy标记的下传问题,这个题目是点权,和之前边权的题目有点不太一样的地方是关于沿着树链修改的时候,每个点都要遍历到,也就是说当a==b的时候不能直接返回了,单个点也是需要修改的,具体的看代码注释吧

代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=5e4+100;int n,m,w;int val[N];vector<int>node[N];int deep[N],fa[N],son[N],num[N];void dfs1(int u,int f,int dep)
{deep[u]=dep;son[u]=-1;num[u]=1;fa[u]=f;for(auto v:node[u]){if(v==f)continue;dfs1(v,u,dep+1);num[u]+=num[v];if(son[u]==-1||num[son[u]]<num[v])son[u]=v;}
}int id[N],idd[N],top[N],cnt;//id[节点]=编号 idd[编号]=节点 void dfs2(int u,int f,int root)
{top[u]=root;id[u]=++cnt;idd[cnt]=u;if(son[u]!=-1)dfs2(son[u],u,root);for(auto v:node[u]){if(v==f||v==son[u])continue;dfs2(v,u,v);}
}struct Node
{int l,r,lazy,sum;int mid(){return l+r>>1;}int cal_len(){return r-l+1;}
}tree[N<<2];void pushup(int k)
{tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}void pushdown(int k)
{int lz=tree[k].lazy;tree[k<<1].sum+=tree[k<<1].cal_len()*lz;tree[k<<1|1].sum+=tree[k<<1|1].cal_len()*lz;tree[k<<1].lazy+=lz;tree[k<<1|1].lazy+=lz;tree[k].lazy=0;
}void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;tree[k].lazy=0;if(l==r){tree[k].sum=val[idd[l]];return;}int mid=tree[k].mid();build(k<<1,l,mid);build(k<<1|1,mid+1,r);pushup(k);
}void update(int k,int l,int r,int val)
{if(tree[k].r<l||tree[k].l>r)return;if(tree[k].l>=l&&tree[k].r<=r){tree[k].lazy+=val;tree[k].sum+=tree[k].cal_len()*val;return;}if(tree[k].lazy)pushdown(k);update(k<<1,l,r,val);update(k<<1|1,l,r,val);pushup(k);
}int query(int k,int pos)
{if(tree[k].l==tree[k].r)return tree[k].sum;if(tree[k].lazy)pushdown(k);int mid=tree[k].mid();if(mid>=pos)return query(k<<1,pos);elsereturn query(k<<1|1,pos);
}void solve(int a,int b,int val)
{while(top[a]!=top[b]){if(deep[top[a]]<deep[top[b]])swap(a,b);update(1,id[top[a]],id[a],val);a=fa[top[a]];}
//    if(a==b)  //这里特意打了注释,就是为了区分点权和边权的区别的,可以好好理解一下为什么要将这句话注释掉
//        return;if(deep[a]<deep[b])swap(a,b);update(1,id[b],id[a],val);return;
}void init()
{for(int i=1;i<=n;i++)node[i].clear();cnt=0;
}int main()
{
//  freopen("input.txt","r",stdin);
//    ios::sync_with_stdio(false);while(scanf("%d%d%d",&n,&m,&w)!=EOF){init();for(int i=1;i<=n;i++)scanf("%d",val+i);for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);node[u].push_back(v);node[v].push_back(u);}dfs1(1,0,0);dfs2(1,0,1);build(1,1,n);while(w--){char s[5];scanf("%s",s);if(s[0]=='I'){int u,v,w;scanf("%d%d%d",&u,&v,&w);solve(u,v,w);}else if(s[0]=='D'){int u,v,w;scanf("%d%d%d",&u,&v,&w);solve(u,v,-w);}else{int x;scanf("%d",&x);printf("%d\n",query(1,id[x]));}}}return 0;
}

HDU - 3966 Aragorn's Story(树链剖分+线段树)相关推荐

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

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

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

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

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

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

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

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

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

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( 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. cv2.threshold() 阈值:使用Python,OpenCV进行简单的图像分割
  2. numpy常用函数之random.normal函数
  3. Java中对List集合排序的两种方法
  4. 爸爸和儿子的故事带你理解java线程
  5. linux 子shell
  6. Syncovery for mac(文件备份和同步工具)
  7. NOIP2018 模拟 Problem A 解题报告 求子序列
  8. groovy+mysql数据库_groovy - groovy连接数据库
  9. 热释电传感器三个引脚_热释电传感器电路图大全(六款热释电传感器电路设计原理图详解)...
  10. spring - 源码下载与构建
  11. 宋宝华Linux培训笔记-Linux内存管理
  12. 收集的省市区下拉数据源
  13. 软件测试 -- 软件缺陷记录的5C原则
  14. jsp界面对数据库增删改查
  15. 腾讯御安全之AI反病毒引擎白皮书
  16. DINO: 让目标检测拥抱Transformer!霸榜COCO!
  17. C语言中write函数
  18. 京东“百亿补贴”提前20小时上线,电商价格战开打; iPhone 15 Pro玻璃面板泄露;凹语言 0.5.0发布|极客头条
  19. Unraid 安装 ZeroTier 实现外网远程操作
  20. Tableau Desktop 2020 Mac支持M1芯片下载big sur 解决M1芯片安装Tableau Public教程2021

热门文章

  1. Nacos自定义 namespace与group配置
  2. 引入OAuth2的主要目的
  3. 索引使用原则-列的离散(sàn)度
  4. Spring 提供哪些配置形式?
  5. 微服务和SOA架构的区别
  6. 如果用户访问一个不存在的地址呢?
  7. AdminLTE介绍
  8. SpringBoot_配置-外部配置加载顺序
  9. 物理设计-如何存储日期类型
  10. 如何判断对象是否存活之引用计数发