题目http://acm.hdu.edu.cn/showproblem.php?pid=5692
题目说每个点至多经过一次,那么就是只能一条路线走到底的意思,看到这题的格式,
多个询问多个更新,
自然而然的就会想到线段树或者树状数组,在建树前先做处理,
用DFS将从起点0出发到任一点的距离求出,
然后将这些节点按照一条一条完整的路线的顺序建到树中,
比如样例是1---2---3
|
6 ---4----5
所以建树的其中一种顺序是1 4 5 6 2 3 。当查询的时候的区间应该是从现在这个点开始到这条路线上的终点,更新的时候也是这个区间更新,相当于把这个区间的所有数都加上一个数,与 poj 3468 类似,lazy操作。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long ll; 8 const int M = 1e5 + 10; 9 int head[M],cas,num[M],ans,st[M],ed[M]; 10 ll sum[M],a[M]; 11 12 ll max(ll x,ll y) {return x>y?x:y;} 13 14 struct Edge{ 15 int to; 16 int next; 17 }edge[M*2]; 18 19 void add(int x,int y) 20 { 21 edge[cas].to=x; 22 edge[cas].next=head[y]; 23 head[y]=cas++; 24 } 25 26 void dfs(int x,int y) 27 { 28 st[x]=++ans;num[ans]=x; 29 sum[x]+=sum[y]; 30 for (int i=head[x] ; i!=-1 ; i=edge[i].next) 31 { 32 int v=edge[i].to; 33 if (v==y) continue; 34 dfs(v,x); 35 } 36 ed[x]=ans; 37 } 38 struct Tree{ 39 int l,r; 40 ll ans,mark; 41 }tree[M*4]; 42 43 void down(int i) 44 { 45 if(tree[i].mark) 46 { 47 tree[i*2].mark+=tree[i].mark;tree[i*2+1].mark+=tree[i].mark; 48 tree[i*2].ans+=tree[i].mark;tree[i*2+1].ans+=tree[i].mark; 49 tree[i].mark=0; 50 } 51 } 52 53 void build(int i,int left,int right) 54 { 55 tree[i].l=left;tree[i].r=right; 56 tree[i].mark=0; 57 if (left==right){tree[i].ans=sum[num[left]];return ;} 58 int mid=(left+right)/2; 59 build(i*2,left,mid); 60 build(i*2+1,mid+1,right); 61 tree[i].ans=max(tree[i*2].ans,tree[i*2+1].ans); 62 } 63 64 ll findest(int i,int left,int right) 65 { 66 if(tree[i].l>=left&&tree[i].r<=right) 67 return tree[i].ans; 68 down(i); 69 int mid=(tree[i].l+tree[i].r)/2; 70 if(mid>=right){return findest(i*2,left,right);} 71 else if(mid<left){return findest(i*2+1,left,right);} 72 else{return max(findest(i*2,left,mid),findest(i*2+1,mid+1,right));} 73 74 } 75 void update(int i,int left,int right,ll pos) 76 { 77 if(tree[i].l>=left&&tree[i].r<=right){tree[i].mark+=pos;tree[i].ans+=pos;return;} 78 int mid=(tree[i].l+tree[i].r)/2; 79 down(i); 80 if(mid<left) update(i*2+1,left,right,pos); 81 else if(mid>=right) update(i*2,left,right,pos); 82 else 83 { 84 update(i*2,left,mid,pos); 85 update(i*2+1,mid+1,right,pos); 86 } 87 tree[i].ans=max(tree[i*2].ans,tree[i*2+1].ans); 88 } 89 90 int main() 91 { 92 int t,n,m,e=0; 93 scanf("%d",&t); 94 while (t--) 95 { 96 printf("Case #%d: ",++e); 97 scanf("%d%d",&n,&m); 98 memset(head,-1,sizeof(head)); 99 for (int i=1 ; i<n ; i++){ 100 int a,b; 101 scanf("%d%d",&a,&b); 102 a++,b++; 103 add(a,b);add(b,a); 104 } 105 cas=0;ans=0; 106 for (int i=1 ; i<=n ; i++) scanf("%I64d",&a[i]),sum[i]=a[i]; 107 dfs(1,0); 108 build(1,1,n); 109 while (m--) 110 { 111 int w,b;ll c; 112 scanf("%d",&w); 113 if (w){ 114 scanf("%d",&b);b++; 115 printf("%I64d ",findest(1,st[b],ed[b])); 116 } 117 else{ 118 scanf("%d%I64d",&b,&c);b++; 119 ll q=c-a[b]; 120 a[b]=c; 121 update(1,st[b],ed[b],q); 122 } 123 } 124 } 125 return 0; 126 }