其实 讲道理这是一道不难的“裸题”
现在是 凌晨两点 ,不想打太多字,进入正题吧:
题意中文 :
百度科技园内有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零食机的路线中,价值总和的最大值。
用dfs序 把 这棵树 的所有节点跑出来
那么对于 节点x , 我们 有区间 L[x]—-R[x] , 这之间的就是x 的子树,我们只需要维护 这个区间的最大值就行了, 如果 对于节点x 增加y, 那么我们只需要 对x 的所有子树都+y ,然后维护L[x]—-R[x] 的最大值就行了, 而x 的所有子树 就在L[x]—-(L[x]+R[x])/2 和 -(L[x]+R[x])/2 +1———R[x] 这两个区间里面啊。 这很典型的用线段树 维护啊。
自己手写的 有巨几把多的自己写搓的地方 ,代码中 注释出来了
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<stdlib.h>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#define mem(a) memset(a,0,sizeof(a))
#define INF 0x7fffffff //INT_MAX
#define inf 0x3f3f3f3f //
const double PI = acos(-1.0);
const double e = exp(1.0);
template<class T> T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<class T> T lcm(T a, T b) { return a / gcd(a, b) * b; }
bool cmpbig(int a,int b){return a>b;}
bool cmpsmall(int a,int b){return a<b;}
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000")
const int MAXN=100005;
struct Edge{
int to;
int next;
};
Edge edge[MAXN*2];
int head[MAXN];
int tot,cnt;
int R[MAXN],L[MAXN];
void dfs(int u,int pre){
L[u]=++cnt;
for(int i=head[u];i!=-1 ; i=edge[i].next){
int v=edge[i].to;
if(v==pre) continue;
dfs(v,u);
}
R[u]=cnt;
}
void addedge(int u,int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
}
struct segtree{
int l,r;
__int64 flag;
__int64 cnt;
void add(__int64 val){
cnt+=val;
flag+=val;
}
} st[MAXN*4];
void build(int l,int r,int rt){
st[rt].cnt=st[rt].flag=0;
st[rt].l=l;
st[rt].l=r;
if(l==r)
return;
int mid=(l+r)>>1;
build(l,mid,rt*2);
build(mid+1,r,rt*2+1);
}
void push_up(int rt){ // 因为每个节点的 x ,其实都已经加到下面的子节点中了;
st[rt].cnt= max( st[rt*2].cnt , st[rt*2+1].cnt);
}
void push_down(int rt){
if(st[rt].flag){
if(st[rt].l==st[rt].r) return;
st[rt*2].add(st[rt].flag); // 这里怎么可能去加 st[rt].cnt????我真是醉了
st[rt*2+1].add(st[rt].flag);
st[rt].flag=0;
}
}
void up(int p,int l,int r,int rt,__int64 val){
int left=L[p];
int rig=R[p];
if(left<=l && r<=rig){
// printf("befor p %d %d %I64d\n",p,rt,st[rt].cnt);
st[rt].add(val);// 去更改 st[p] 是不是傻逼???
// printf("after p %d %d %I64d\n",p,rt,st[rt].cnt);
return;
}
push_down(rt);
int mid=(l+r)>>1;
if(mid>=rig) up(p,l , mid,rt*2 , val);
else if(mid< left) up(p,mid+1,r ,rt*2+1,val);
else{
up(p,l , mid,rt*2 , val);up(p,mid+1,r ,rt*2+1,val);
}
push_up(rt);
}
__int64 ask(int p,int l,int r,int rt){
int left=L[p];
int rig=R[p];
if(left<=l && r <=rig){
return st[rt].cnt;
}
push_down(rt);
int mid=(l+r)>>1;
__int64 ans; // 这里怎么可能写 st[rt].cnt呢, 只有节点上的值是我们要取得
if(mid>=rig) ans=ask(p,l , mid,rt*2) ;
else if(mid< left) ans=ask(p,mid+1,r ,rt*2+1);
else ans=max(ask(p,mid+1,r ,rt*2+1),ask(p,l , mid,rt*2) );
push_up(rt);
return ans;
}
int f[MAXN];
void init(){
memset(head,-1,sizeof(head));
tot=cnt=0;
}
int main(){
//freopen("1.txt","r",stdin);
int t;
scanf("%d",&t);
for(int k=1;k<=t;k++){
init();
printf("Case #%d:\n",k);
int n,m,i;
scanf("%d%d",&n,&m);
build(1,n,1);
for( i=1;i<n;i++){
int a,b;
scanf("%d %d",&a,&b);a++,b++;
addedge(a,b);
addedge(b,a);
}
dfs(1,0);
for( i=1;i<=n;i++){
scanf("%d",&f[i]);
up(i,1,n,1,f[i]);
}
while(m--){
int op;
scanf("%d",&op);
int x;
scanf("%d",&x);x++;
if(op){
printf("%I64d\n",ask(x,1,n,1));
}
else{
int y;
scanf("%d",&y);
up(x,1,n,1,y-f[x]); //这个地方用 i 我也真是醉了
f[x]=y;
}
}
}
}
/*
_ooOoo_
o8888888o
88" . "88
(| -_- |)
O\ = /O
____/`---'\____
.' \\| |// `.
/ \\||| : |||// \
/ _||||| -:- |||||- \
| | \\\ - /// | |
| \_| ''\---/'' | |
\ .-\__ `-` ___/-. /
___`. .' /--.--\ `. . __
."" '< `.___\_<|>_/___.' >'"".
| | : `- \`.;`\ _ /`;.`/ - ` : | |
\ \ `-. \_ __\ /__ _/ .-` / /
======`-.____`-.___\_____/___.-`____.-'======
`=---='
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
佛祖保佑 永无BUG
*/