您的位置:首页 > 理论基础 > 数据结构算法

HDU 5692 线段树

2016-05-21 19:58 453 查看
点击打开链接

题意:中文题目

思路:这还是第一次写这样的线段树,个人感觉是一种套路之前没做过,但是思想什么巧妙,将一颗树转化成线段树真厉害,先是将每个节点的下面的所有数进行dfs编序号,并将他们的左右编号记下来,也就是我的代码中的L和R,而val记录的是根节点0到当前位置的费用,建树之后就很好操作了,更新时便找到当前节点的儿子和自己代表的区间,然后区间更新,注意题目说更新一个节点的值变为y,我们为什么更新一段,因为我们线段树的节点保存的是到根节点0的费用,那么作为一个父亲节点,它的值变了,自然会影响它的所有儿子到根节点的费用,而且变化的相同,所以用区间更新来完成,查询也是一样,必须到x节点,那么到了x节点后是不是还会有更大的费用呢,而这个费用的点肯定要经过x节点,所以我们直接查询x节点和它的所有儿子的最大值即可
   PS:树形的结构与线段树完美结合,要好好练练才行#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int maxn=100010;
vector<int>G[maxn];
ll max1[maxn*4],lazy[maxn*4],val[maxn];
int L[maxn],R[maxn],cost[maxn];
int idx;
void dfs(int u,int f,ll vv){
L[u]=++idx;
for(unsigned int i=0;i<G[u].size();i++){
int v=G[u][i];
if(v==f) continue;
dfs(v,u,(ll)cost[v]+vv);
}
R[u]=idx;
val[L[u]]=vv;
}
void pushup(int node){
max1[node]=max(max1[node<<1],max1[node<<1|1]);
}
void pushdown(int node){
if(lazy[node]){
lazy[node<<1]+=lazy[node];
lazy[node<<1|1]+=lazy[node];
max1[node<<1]+=lazy[node];
max1[node<<1|1]+=lazy[node];
lazy[node]=0;
}
}
void buildtree(int le,int ri,int node){
if(le==ri){
max1[node]=val[le];
return ;
}
int t=(le+ri)>>1;
buildtree(le,t,node<<1);
buildtree(t+1,ri,node<<1|1);
pushup(node);
}
void update(int l,int r,int x,int le,int ri,int node){
if(l<=le&&ri<=r){
lazy[node]+=(ll)x;
max1[node]+=(ll)x;
return ;
}
pushdown(node);
int t=(le+ri)>>1;
if(l<=t) update(l,r,x,le,t,node<<1);
if(r>t) update(l,r,x,t+1,ri,node<<1|1);
pushup(node);
}
ll query(int l,int r,int le,int ri,int node){
if(l<=le&&ri<=r) return max1[node];
pushdown(node);
ll ans=-inf;
int t=(le+ri)>>1;
if(l<=t) ans=max(ans,query(l,r,le,t,node<<1));
if(r>t) ans=max(ans,query(l,r,t+1,ri,node<<1|1));
return ans;
}
int main(){
int T,cas=1,n,m,a,b,c;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=0;i<maxn;i++) G[i].clear();
for(int i=0;i<n-1;i++){
scanf("%d%d",&a,&b);
a++;b++;
G[a].push_back(b);
G[b].push_back(a);
}
for(int i=1;i<=n;i++) scanf("%d",&cost[i]);
idx=0;dfs(1,0,(ll)cost[1]);
buildtree(1,n,1);
memset(lazy,0,sizeof(lazy));
printf("Case #%d:\n",cas++);
while(m--){
scanf("%d",&a);
if(a==0){
scanf("%d%d",&b,&c);b++;
update(L[b],R[b],c-cost[b],1,n,1);
cost[b]=c;
}else{
scanf("%d",&b);b++;
ll answe=query(L[b],R[b],1,n,1);
printf("%I64d\n",answe);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM 数据结构 线段树