[2016"百度之星" - 初赛(Astar Round2A)]Snacks

xiaoxiao2025-09-18  5

Pro

QwQ

Sol

其实就是求以x为根的子树到0点的距离最大值。用dfs序把每一个结点对应的子树区间和到0点的距离求出来,挂到线段树上,修改的时候直接在线段树上修改整个区间即可。

(不太详细,待更……)

Code

爆搜代码

#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int L = 100005; struct Node { int to , next; }; Node e[2*L]; int T , n , m , val[L] , head[L] , tot , ans , flag; void add(int x , int y) { tot++; e[tot].next = head[x]; e[tot].to = y; head[x] = tot; } int dfs(int u , int f , int aim) { if(u==aim) { flag = f; return 1; } for(int i=head[u]; i; i=e[i].next) { int v = e[i].to; if(v==f) continue; if(dfs(v , u , aim)) { ans += val[v]; return 1; } } return 0; } void dfs2(int u , int f) { for(int i=head[u]; i; i=e[i].next) { int v = e[i].to; if(v==f||val[v]<0) continue; ans += val[v]; dfs2(v , u); } } int main() { scanf("%d",&T); for(int t=1; t<=T; t++) { memset(head , 0 , sizeof(head)); tot = 0; scanf("%d%d",&n,&m); for(int i=1; i<n; i++) { int x , y; scanf("%d%d",&x,&y); add(x , y); add(y , x); } for(int i=0; i<n; i++) scanf("%d",&val[i]); printf("Case #%d:\n",t); for(int i=1; i<=m; i++) { int opt; scanf("%d",&opt); if(opt==0) { int x , y; scanf("%d%d",&x,&y); val[x] = y; } else { int x; scanf("%d",&x); ans = val[0]; dfs(0 , 0 , x); dfs2(x , flag); printf("%d\n",ans); } } } return 0; }

正解代码

#pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cstring> #define INF 1e18 using namespace std; const long long L = 100005; struct Node { long long to , next; }; Node e[2*L]; struct Seg { long long l , r , sum , lazy; }; Seg tree[4*L]; long long T , n , m , val[L] , head[L] , tot , num , d[L] , l[L] , r[L] , nd[L]; inline long long mymax(long long a , long long b) { return a>b?a:b; } void add(long long x , long long y) { tot++; e[tot].next = head[x]; e[tot].to = y; head[x] = tot; } void dfs(long long u , long long f) { num++; l[u] = num; nd[num] = u; for(int i=head[u]; i; i=e[i].next) { long long v = e[i].to; if(v==f) continue; d[v] = d[u] + val[v]; dfs(v , u); } r[u] = num; } void build(long long num , long long l , long long r) { tree[num].l = l; tree[num].r = r; tree[num].lazy = 0; if(l==r) { tree[num].sum = d[nd[l]]; return ; } long long mid = (l+r)>>1; build(num<<1 , l , mid); build(num<<1|1 , mid+1 , r); tree[num].sum = mymax(tree[num<<1].sum , tree[num<<1|1].sum); } void pushdown(long long num) { if(tree[num].lazy) { tree[num<<1].sum += tree[num].lazy; tree[num<<1|1].sum += tree[num].lazy; tree[num<<1].lazy += tree[num].lazy; tree[num<<1|1].lazy += tree[num].lazy; tree[num].lazy = 0; } } void update(long long num , long long l , long long r , long long add) { if(l<=tree[num].l&&r>=tree[num].r) { tree[num].lazy += add; tree[num].sum += add; return ; } long long mid = (tree[num].l+tree[num].r)>>1; pushdown(num); if(l<=mid) update(num<<1 , l , r , add); if(mid<r) update(num<<1|1 , l , r , add); tree[num].sum = mymax(tree[num<<1].sum , tree[num<<1|1].sum); } long long query(long long num , long long l , long long r) { if(l<=tree[num].l&&r>=tree[num].r) return tree[num].sum; long long mid = (tree[num].l+tree[num].r)>>1; pushdown(num); long long ans = -INF; if(l<=mid) ans = mymax(ans , query(num<<1 , l , r)); if(r>mid) ans = mymax(ans , query(num<<1|1 , l , r)); return ans; } int main() { scanf("%lld",&T); for(int t=1; t<=T; t++) { num = 0; memset(head , 0 , sizeof(head)); tot = 0; scanf("%lld%lld",&n,&m); for(int i=1; i<n; i++) { long long x , y; scanf("%lld%lld",&x,&y); add(x , y); add(y , x); } for(int i=0; i<n; i++) scanf("%lld",&val[i]); d[0] = val[0]; dfs(0 , -1); build(1 , 1 , n); printf("Case #%d:\n",t); for(int i=1; i<=m; i++) { long long opt; scanf("%lld",&opt); if(opt==0) { long long x , y; scanf("%lld%lld",&x,&y); update(1 , l[x] , r[x] , y-val[x]); val[x] = y; } else { long long x; scanf("%lld",&x); printf("%lld\n",query(1 , l[x] , r[x])); } } } return 0; }
转载请注明原文地址: https://www.6miu.com/read-5036551.html

最新回复(0)