Snacks HDU 5692 dfs序列+线段树

题意

百度科技园内有n个零食机,零食机之间通过n−1条路相互连通。每个零食机都有一个值v,表示为小度熊提供零食的价值。

由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。

为小度熊规划一个路线,使得路线上的价值总和最大

输入输出:

输入数据第一行是一个整数T(T≤10),表示有T组测试数据。

对于每组数据,包含两个整数n,m(1≤n,m≤100000),表示有n个零食机,m次操作。

接下来n−1行,每行两个整数x和y(0≤x,y<n),表示编号为x的零食机与编号为y的零食机相连。

接下来一行由n个数组成,表示从编号为0到编号为n−1的零食机的初始价值v(|v|<100000)。

接下来m行,有两种操作:0 x y,表示编号为x的零食机的价值变为y;1 x,表示询问从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。

本题可能栈溢出,辛苦同学们提交语言选择c++,并在代码的第一行加上:

#pragma comment(linker, "/STACK:1024000000,1024000000") 

题解思路

dfs序列的题,这是第一道,当然不出意外,我不会做。但是我找到一篇写的非常好的博客,详细解释了这个题。点我链接

思路就是用dfs序列,将树“拍”成一维的一串,这样就可以用线段树或者树状数组进行接下来的操作了。

至于为什么要转化为一维的,因为简单啊,并且用来处理一维数据的方法也很多。

代码实现

两种形似,第一个是数组形式的线段树,有注释。第二种是使用结构体线段树,和第一种基本一样。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>using namespace std;vector <int> a[100001];
int n,m,now = 0,b[100001],xulie[100005],e[100005];
long long v[100005],dis[100005] ={0},maxsum[100005*4],lazy_tag[100005*4] = {0};void dfs(int x,int pre)//深搜找dfs序
{b[x] = ++now;//这是这个节点的开始位置xulie[now] = x;//把这个序号的节点加入到序列中int len = a[x].size();//这是x节点的出度for(int i = 0;i <= len-1;i++)//vector是从0开始计数的{int y = a[x][i];//x的一个出度。if (y!=pre)//如果没有往回走{dis[y] = dis[x]+v[y];//更新y节点它到0点的价值和dfs(y,x);//继续dfs}}e[x] = now;//这是节点的结束位置。b[x]..e[x]里面存的都是x的子树节点。
}long long max(long long a,long long b)
{return a > b?a:b;
}void push_up(int rt)
{maxsum[rt] = max(maxsum[rt<<1],maxsum[rt<<1|1]);//只要左右区间的最值取max就可以了。
}void build(int l,int r,int rt)
{lazy_tag[rt] = maxsum[rt] = 0;//初始化懒惰标记和区间最值。if (l == r)//如果左右指针相同{maxsum[rt] = dis[xulie[l]];//这个区间的最大值就是本身return;//注意不要写成maxsum[rt] = dis[l],l是dfs序,xulie[l]才是这个dfs序所代表的点}int m = (l+r)>>1;//取得中点build(l,m,rt<<1);//左递归建树build(m+1,r,rt<<1|1);//右递归建树push_up(rt);//根据儿子更新当前区间的最值。
}void push_down(int rt)
{if (lazy_tag[rt]!=0) //如果懒惰标记标记的值不为0{maxsum[rt<<1]+=lazy_tag[rt];//更新儿子节点们的区间最值(记住是同等更新就好)maxsum[rt<<1|1] += lazy_tag[rt];lazy_tag[rt<<1]+=lazy_tag[rt];//更新儿子节点们的懒惰标记。lazy_tag[rt<<1|1]+=lazy_tag[rt];lazy_tag[rt]=0;//把当前节点的懒惰标记置为0;}
}void updata(int l,int r,int num,int begin,int end,int rt) //所要修改的区间为l,r,当前节点rt的区间
{//为begin,end,然后要递增的值为numif (l <= begin && end <= r) //如果当前节点所在的区间被所要修改的区间覆盖{maxsum[rt]+=num;//递增这个区间的最大值(因为是同等递增,所以直接把最大值+递增值就可以);lazy_tag[rt] +=num;//标一个懒惰标记。return;}push_down(rt);//处理懒惰标记。int m = (begin+end)>>1;//取中点if (l <= m)//往左递增值updata(l,r,num,begin,m,rt<<1);if (m < r)//往右递增值。updata(l,r,num,m+1,end,rt<<1|1);push_up(rt);//根据儿子节点更新当前节点。
}long long query(int l,int r,int begin,int end,int rt)//要找的区间为l,r,当前节点rt所代表的区间为begin,end;
{if (l <= begin && end <= r)//如果当前节点所在的区间完全在要找的区间内return maxsum[rt];//就直接返回这个区间的最大值long long temp_ans= -10000000000;//这是用于取左右区间最大值的较大值。int m = (begin+end)>>1;push_down(rt);//先处理懒惰标记!!!!!!!!!!!!if (l <= m)//如果左区间和所找的区间有交集,就看看左区间是否更大temp_ans = max(temp_ans,query(l,r,begin,m,rt<<1));if (m < r)//右区间同理temp_ans = max(temp_ans,query(l,r,m+1,end,rt<<1|1));return temp_ans;//返回左右区间的较大值即可。
}int main()
{//freopen("rush.txt","r",stdin);int t;scanf("%d",&t);//输入数据的组数for (int ii = 1;ii <= t;ii++)//不要写成while (t--)。。。这样写你要怎么输出呢。。。{now = 0;//dfs序号从0再重新开始for (int i = 0;i <= 100000;i++)//初始化某个点的出度信息。a[i].clear();printf("Case #%d:\n",ii);//输出这是第几组数据scanf("%d%d",&n,&m);//输入点和边的信息。for (int i = 1;i <= n-1;i++)//输入n-1条边(就是树了!){int x,y;scanf("%d%d",&x,&y);//输入起点和终点a[x].push_back(y);//建一条双向边。a[y].push_back(x);}for (int i = 0;i <= n-1;i++)//输入点的初始价值。scanf("%lld",&v[i]);dis[0] = v[0];//从0到0就是0点的价值。dfs(0,-1);//进行dfs,获取0到所有点的价值和。build(1,n,1);//建树。for (int i = 1;i <= m;i++)//输入m个操作。{int op,x,y;scanf("%d",&op);//读取操作if (op == 0)//如果要改变某个值{scanf("%d%d",&x,&y);updata(b[x],e[x],y-v[x],1,n,1);//把替换操作改为递增操作。要进行修改的区间就是v[x] = y;//x的子树所在的区间。//v[x]下次可能还会用到所以要修改一下。}else{scanf("%d",&x);//读入x,表示要经过x(然后从x和x的子树节点里面选一个节点到那里)cout << query(b[x],e[x],1,n,1) << endl;//在x的子树节点所在区间内找最大价值}}}return 0;
}
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=1e5+7;
int in[maxn], out[maxn], xulie[maxn];
ll dis[maxn], v[maxn];
vector<int> g[maxn];
struct node{int l, r;ll maxx, lazy;
}t[maxn<<2];
int n, m, now;
void init()
{now=0;for(int i=0; i<=n; i++){g[i].clear();}
}
void dfs(int rt, int fa)
{in[rt]=++now;xulie[now]=rt;int len=g[rt].size();for(int i=0; i<len; i++){int y=g[rt][i];if(y==fa) continue;dis[y]=dis[rt]+v[y];dfs(y, rt);}out[rt]=now;
}
void pushup(int rt)
{t[rt].maxx=max(t[rt<<1].maxx, t[rt<<1|1].maxx);
}
void build(int rt, int l, int r)
{t[rt].l=l;t[rt].r=r;t[rt].lazy=0;if(l==r){t[rt].maxx=dis[xulie[l]];return ;}int mid=(l+r)>>1;build(rt<<1, l, mid);build(rt<<1|1, mid+1, r);pushup(rt);
}
void down(int rt)
{if(t[rt].lazy!=0){t[rt<<1].maxx+=t[rt].lazy;t[rt<<1].lazy+=t[rt].lazy;t[rt<<1|1].maxx+=t[rt].lazy;t[rt<<1|1].lazy+=t[rt].lazy;t[rt].lazy=0;}
}
void update(int rt, int l, int r, int y)
{if(l<=t[rt].l && t[rt].r <=r){t[rt].maxx+=y;t[rt].lazy+=y;return ;}down(rt);int mid=(t[rt].l+t[rt].r)>>1;if(l<=mid) update(rt<<1, l, r, y);if(r>mid) update(rt<<1|1, l, r, y);pushup(rt);
}
ll query(int rt, int l, int r)
{if(l<= t[rt].l && t[rt].r<=r){return t[rt].maxx;}ll ans=-1e18;int mid=(t[rt].l+t[rt].r)>>1;down(rt);if(l<=mid) ans=max(ans, query(rt<<1, l, r));if(r>mid) ans=max(ans, query(rt<<1|1, l, r));return ans;
}
int main()
{int t;scanf("%d", &t);for(int ca=1; ca<=t; ca++){scanf("%d%d", &n, &m);init();printf("Case #%d:\n", ca);for(int i=1; i<n; i++){int x, y;scanf("%d%d", &x, &y);g[x].push_back(y);g[y].push_back(x);}for(int i=0; i<=n-1; i++){scanf("%lld", &v[i]);}dis[0]=v[0];dfs(0, -1);build(1, 1, n);for(int i=1; i<=m; i++){int op, x, y;scanf("%d", &op);if(op==0){scanf("%d%d", &x, &y);update(1,in[x], out[x], y-v[x]);v[x]=y;}else {scanf("%d", &x);printf("%lld\n", query(1, in[x], out[x]));}}}return 0;
} 

转载于:https://www.cnblogs.com/alking1001/p/11383492.html

Snacks HDU 5692 dfs序列+线段树相关推荐

  1. codeforces 877E. Danil and a Part-time Job (DFS序列+线段树)

    传送门:codeforces 877E 题目大意: 有一颗树,树的每个节点有一盏灯,状态为亮或灭.现在可以进行以下两种操作: 1.pow x,将以 x 为根节点的子树(包括根节点)的所有节点的灯的状态 ...

  2. New Year Tree(dfs序+线段树+二进制)

    题意: 给出一棵 n个节点的树,根节点为 1.每个节点上有一种颜色 ci.m次操作.操作有两种: 1 u c:将以 u为根的子树上的所有节点的颜色改为c. 2 u:询问以 u为根的子树上的所有节点的颜 ...

  3. 求和(dfs序+线段树)

    题意: 已知有n个节点,有n−1条边,形成一个树的结构. 给定一个根节点k,每个节点都有一个权值,节点i的权值为vi​. 给m个操作,操作有两种类型: 1 a x :表示将节点a的权值加上x 2 a ...

  4. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

  5. codeforces E. Jamie and Tree LCA+dfs序+线段树

    题解: 写起来还稍微有点麻烦. dfs序+线段树可以维护子树的整体修改和查询. 因此,这道题我们要往子树上靠. 我们首先从1号点进行dfs遍历,顺便求出点的dfs序和深度,然后我们采用倍增的思想,可以 ...

  6. Codeforces 343D Water Tree(DFS序 + 线段树)

    题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...

  7. [CodeForces877 E. Danil and a Part-time Job]dfs序+线段树

    [CodeForces877 E.Danil and a Part-time Job]dfs序+线段树 分类:Data Structure SegMent Tree dfn 1. 题目链接 [Code ...

  8. bzoj3252攻略 贪心+dfs序+线段树

    题目链接:戳这里 3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 605  Solved: 255 [Submit][Status] ...

  9. 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 339  Solved: 130 [Submit][Status][Discuss] ...

  10. dfs序+线段树 BZOJ3252 攻略

    3252: 攻略 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 496  Solved: 211 [Submit][Status][Discuss] ...

最新文章

  1. react native 的底部导航栏以及跳转页面带参数
  2. [Asp.net]站点地图SiteMap
  3. 阅读《第31次中国互联网络发展状况统计报告》,分析中国互联网发展趋势和特点...
  4. 洛谷 - P4768 [NOI2018]归程(Kruskal重构树+树上倍增+最短路)
  5. 华为手机怎么使用读卡器_华为手机使用小窍门
  6. django上传文件到服务器,如何用django将文件上传到服务器?
  7. 华为私有云的搭建方案_华为云搭建word press
  8. 硬板床害死中国人?西方人都睡软床垫?究竟是谁睡错了?
  9. linux内实践核分析模块
  10. linux下编辑文件实验,Linux上最常用的文本编辑器vi/vim使用教程
  11. Is It A Tree?(hdu1325)
  12. 设计模式之美 - 64状态模式
  13. mysql中的where和having子句的区别
  14. python dicom放大_python3实现对dicom图像处理(图像呈现,缩放,平移)
  15. flutter用英语怎么说_手机流量套餐用英语怎么说?
  16. 计算机如何添加gust用户,win7系统如何创建安全的Guest账户
  17. 实时训练Real-Time Training 教程
  18. 手动爬取炉石传说所有卡牌
  19. win10系统 oracle11g的安装流程
  20. 小娱路由php,跟风折腾小娱路由器XY-C5,做低功耗路由+下载器+轻量化NAS.

热门文章

  1. idea开发springboot的一些小干货
  2. 用户只有一部手机,怎么保护私钥—— mixin如何实现资产安全
  3. 安装Centos7时提示 /dev/root does not exits
  4. Python nose测试工具报ImportError: No Module named 错误
  5. I.MX6 busybox set hosname and login with root
  6. Windows UWP开发系列 – 控件默认样式
  7. Message Authentication Code
  8. 菜鸟的IT道路ing (六)
  9. (转)C#Interface简介
  10. 项目实战中的防御性编程