HDU5692:DFS序+线段树
HDU5692:Snacks
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 5756 Accepted Submission(s): 1306
Problem Description
百度科技园内有n个零食机,零食机之间通过n−1条路相互连通。每个零食机都有一个值v,表示为小度熊提供零食的价值。
由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。
为小度熊规划一个路线,使得路线上的价值总和最大。
Input
输入数据第一行是一个整数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") `
Output
对于每组数据,首先输出一行”Case #?:”,在问号处应填入当前数据的组数,组数从1开始计算。
对于每次询问,输出从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。
Sample Input
1
6 5
0 1
1 2
0 3
3 4
5 3
7 -5 100 20 -5 -7
1 1
1 3
0 2 -1
1 1
1 5
Sample Output
Case #1:
102
27
2
20
Source
2016"百度之星" - 初赛(Astar Round2A)
Recommend
wange2014 | We have carefully selected several similar problems for you: 6460 6459 6458 6457 6456
题解
DFS序一遍,再用线段树维护前缀和。求经过x的最大,即求线段树[id[x],id[x]+sz[x]-1]区间的最大值,id[x]为xDFS序后的新编号,sz[x]为子树(包括本身)的大小。把x编号的值改为y,即区间[id[x],id[x]+sz[x]-1]同时加上该变量y-cost[x]。线段树用lazy标志。
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
int const N = 100000 + 10;
ll const inf = 1e18; //不能用int const inf = 0x7f7f7f7f;
ll n,m,T,tot;
ll first[N],ne[N<<2],to[N<<2],sz[N],id[N];
ll w[N],wt[N];
struct Node
{
ll l,r;
ll sum,lazy;
void updata(ll val){
sum += val; //区间更新,求区间最大值;
lazy += val;
}
}node[N<<2];
void add(ll x,ll y){
ne[++tot] = first[x];
to[tot] = y;
first[x] = tot;
}
void dfs(ll u,ll f){
id[u] = ++tot;
if(f == -1) wt[tot] = w[u];
wt[tot] = wt[id[f]] + w[u];
sz[u] = 1;
for(ll i=first[u];i;i=ne[i]){
ll v = to[i];
if(v == f) continue;
dfs(v,u);
sz[u] += sz[v];
}
}
void push_down(ll id){
ll lazy = node[id].lazy;
if(lazy){
node[id<<1].updata(lazy);
node[id<<1|1].updata(lazy);
node[id].lazy = 0;
}
}
void push_up(ll id){
node[id].sum = max(node[id<<1].sum,node[id<<1|1].sum);
}
void build(ll id,ll l,ll r){
node[id].l = l, node[id].r = r;
node[id].lazy = node[id].sum = 0;
if(l == r){
node[id].sum = wt[l];
}else{
ll mid = (l + r) >> 1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
push_up(id);
}
}
void updata(ll id,ll L,ll R,ll k){
ll l = node[id].l, r = node[id].r;
if(L <=l && r <= R){
node[id].updata(k);
}else{
ll mid = (l + r) >> 1;
push_down(id);
if(L <= mid) updata(id<<1,L,R,k);
if(mid < R) updata(id<<1|1,L,R,k);
push_up(id);
}
}
ll query(ll id,ll L,ll R){
ll l = node[id].l, r = node[id].r;
if(L <= l && r <= R){
return node[id].sum;
}else{
ll mid = (l + r) >> 1;
push_down(id);
ll res = -inf; //注意不能初始化为0,题目给出的v绝对值小于100000.debug了半天。。。
if(L <= mid) res = max(query(id<<1,L,R),res);
if(mid < R) res = max(query(id<<1|1,L,R),res);
//push_up(id);
return res;
}
}
void Init(){
memset(first,0,sizeof(first));
tot = 0;
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n-1;i++){
ll x,y; scanf("%lld%lld",&x,&y);
add(x,y); add(y,x);
}
for(ll i=0;i<=n-1;i++) scanf("%lld",&w[i]);
tot = 0;
dfs(0,-1);
build(1,1,n);
}
void solve(ll caser){
printf("Case #%lld:\n",caser);
ll k,x,y;
for(ll i=1;i<=m;i++){
scanf("%lld",&k);
if(k == 0){
scanf("%lld%lld",&x,&y);
ll change = y - w[x];
updata(1,id[x],id[x]+sz[x]-1,change);
w[x] = y;
}else{
scanf("%lld",&x);
printf("%lld\n",query(1,id[x],id[x]+sz[x]-1));
}
}
}
int main(){
scanf("%lld",&T);
for(ll caser=1;caser<=T;caser++){
Init();
solve(caser);
}
return 0;
}

浙公网安备 33010602011771号