hdu 5692 Snacks(dfs时间戳+线段树)
Snacks
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2165 Accepted Submission(s): 513
Problem Description
百度科技园内有n个零食机,零食机之间通过n−1条路相互连通。每个零食机都有一个值v,表示为小度熊提供零食的价值。
由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。
为小度熊规划一个路线,使得路线上的价值总和最大。
由于零食被频繁的消耗和补充,零食机的价值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") `
对于每组数据,包含两个整数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零食机的路线中,价值总和的最大值。
对于每次询问,输出从编号为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
这题是把树化为线性去处理的典型题。
对于本题我们要求的是经过从根并经过点s的路径最大权值,即到达该点和该点子树上每个节点的路径总权值里的最大值。这个可以用前缀和求出到每个点的总权值。并且这之中带有权值修改,一下就令人想到线段树。但线段树维护的是一个区间上的值,那怎么把一颗树化为线性呢?那么此时dfs时间戳就派上用场了。我们需要把一棵树用dfs时间戳将这棵树化为一个线性的区间,区间每个点存的是dfs时间戳里的节点所对应的从0根节点到该节点的路径总权值。此时我们要求解点s的从根并经过点s的路径最大权值,就变成了求解pre[s]~last[s]这个区间里所有权值的最大值,而修改某个点u的权值相当于更新pre[u]~last[u]里的所有权值。于是该题就能用线段树维护求解了。
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<cstdio> 3 #include<iostream> 4 #include<cstring> 5 #define clr(x) memset(x,0,sizeof(x)) 6 #define clr_1(x) memset(x,-1,sizeof(x)) 7 #define LL long long 8 #define INF (1e18) 9 using namespace std; 10 struct edg 11 { 12 int next,to; 13 }edge[100010<<2]; 14 struct seg 15 { 16 int l,r; 17 LL maxn,tag; 18 }segt[100010<<2]; 19 int head[100010],dfstm[100010],pre[100010],last[100010],n,m,k,u,v,s,T,cnt; 20 LL value[100010],sum[100010],x; 21 LL max(LL a, LL b) 22 { 23 return a>b?a:b; 24 } 25 void addedge(int u,int v) 26 { 27 edge[++cnt].to=v; 28 edge[cnt].next=head[u]; 29 head[u]=cnt; 30 return ; 31 } 32 void dfs(int i,int fa) 33 { 34 sum[i]=sum[fa]+value[i]; 35 dfstm[++k]=i; 36 pre[i]=k; 37 for(int j=head[i];j!=-1;j=edge[j].next) 38 if(edge[j].to!=fa) 39 dfs(edge[j].to,i); 40 last[i]=k; 41 return ; 42 } 43 void init(int i,int l,int r) 44 { 45 segt[i]=(seg){l,r,0,0}; 46 if(l==r) 47 { 48 segt[i].maxn=sum[dfstm[l]]; 49 return; 50 } 51 int mid=(l+r)>>1; 52 init(i<<1,l,mid); 53 init(i<<1|1,mid+1,r); 54 segt[i].maxn=max(segt[i<<1].maxn,segt[i<<1|1].maxn); 55 return ; 56 } 57 void pushdown(int i) 58 { 59 if(segt[i].tag!=0) 60 { 61 if(segt[i].l!=segt[i].r) 62 { 63 segt[i<<1].maxn+=segt[i].tag; 64 segt[i<<1|1].maxn+=segt[i].tag; 65 segt[i<<1].tag+=segt[i].tag; 66 segt[i<<1|1].tag+=segt[i].tag; 67 } 68 segt[i].tag=0; 69 } 70 return ; 71 } 72 void update(int i,int l,int r,LL addval) 73 { 74 if(segt[i].l>=l && segt[i].r<=r) 75 { 76 segt[i].tag+=addval; 77 segt[i].maxn+=addval; 78 return ; 79 } 80 pushdown(i); 81 int mid=(segt[i].l+segt[i].r)>>1; 82 if(mid>=r) 83 { 84 update(i<<1,l,r,addval); 85 } 86 else if(mid<l) 87 { 88 update(i<<1|1,l,r,addval); 89 } 90 else 91 { 92 update(i<<1,l,r,addval); 93 update(i<<1|1,l,r,addval); 94 } 95 segt[i].maxn=max(segt[i<<1].maxn,segt[i<<1|1].maxn); 96 return ; 97 } 98 LL query(int i,int l,int r) 99 { 100 if(segt[i].l>=l && segt[i].r<=r) 101 { 102 return segt[i].maxn; 103 } 104 pushdown(i); 105 int mid=(segt[i].l+segt[i].r)>>1; 106 LL ans=-INF; 107 if(mid>=r) 108 { 109 ans=max(ans,query(i<<1,l,r)); 110 } 111 else if(mid<l) 112 { 113 ans=max(ans,query(i<<1|1,l,r)); 114 } 115 else 116 { 117 ans=max(ans,query(i<<1,l,r)); 118 ans=max(ans,query(i<<1|1,l,r)); 119 } 120 segt[i].maxn=max(segt[i<<1].maxn,segt[i<<1|1].maxn); 121 return ans; 122 } 123 int main() 124 { 125 scanf("%d",&T); 126 for(int kase=1;kase<=T;kase++) 127 { 128 clr_1(head); 129 clr(sum); 130 cnt=0; 131 k=0; 132 printf("Case #%d:\n",kase); 133 scanf("%d%d",&n,&m); 134 for(int i=1;i<n;i++) 135 { 136 scanf("%d%d",&u,&v); 137 addedge(u,v); 138 addedge(v,u); 139 } 140 for(int i=0;i<n;i++) 141 { 142 scanf("%lld",&value[i]); 143 } 144 dfs(0,0); 145 init(1,1,n); 146 for(int i=1;i<=m;i++) 147 { 148 scanf("%d",&k); 149 if(k) 150 { 151 scanf("%d",&u); 152 printf("%lld\n",query(1,pre[u],last[u])); 153 } 154 else 155 { 156 scanf("%d%lld",&u,&x); 157 update(1,pre[u],last[u],x-value[u]); 158 value[u]=x; 159 } 160 } 161 } 162 return 0; 163 }