标签:amp printf names ons 就是 输入数据 typedef put 提交
Input输入数据第一行是一个整数T(T≤10)T(T≤10),表示有TT组测试数据。
对于每组数据,包含两个整数n,m(1≤n,m≤100000)n,m(1≤n,m≤100000),表示有nn个零食机,mm次操作。
接下来n−1n−1行,每行两个整数xx和y(0≤x,y<n)y(0≤x,y<n),表示编号为xx的零食机与编号为yy的零食机相连。
接下来一行由nn个数组成,表示从编号为0到编号为n−1n−1的零食机的初始价值v(|v|<100000)v(|v|<100000)。
接下来mm行,有两种操作:0 x y0 x y,表示编号为xx的零食机的价值变为yy;1 x1 x,表示询问从编号为0的零食机出发,必须经过编号为xx零食机的路线中,价值总和的最大值。
本题可能栈溢出,辛苦同学们提交语言选择c++,并在代码的第一行加上:
`#pragma comment(linker, "/STACK:1024000000,1024000000") `Output对于每组数据,首先输出一行”Case #?:”,在问号处应填入当前数据的组数,组数从1开始计算。
对于每次询问,输出从编号为0的零食机出发,必须经过编号为xx零食机的路线中,价值总和的最大值。
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
题解:大体思路就是首先DFS标记每个点的时间戳,并且记录到每个点的路径(同时开一个Rev数组,从时间戳返回到原节点,建线段树的时候要用到).
知道了每个节点的时间戳,就知道了该节点的子树的区间,为[Start[x],End[x]],更新的话用线段树区间更新,查询的话用线段树区间查询,用到lazy数组.
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=100010; const ll INF=0x3f3f3f3f3f3f3f3f;//这里一定是long long 啊啊啊啊 ll head[maxn],dis[maxn],w[maxn],Rev[maxn]; int Start[maxn],End[maxn]; int tot,cnt,n,m; ll sum[maxn<<2],lazy[maxn<<2]; struct node { ll v,next; }e[maxn<<1]; void add(int u,int v) { e[tot]=(node){v,head[u]}; head[u]=tot++; } void DFS(int u,int pre) { Start[u]=++cnt; Rev[cnt]=u; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v; if(v==pre)continue; dis[v]=dis[u]+w[v]; DFS(v,u); } End[u]=cnt; } void pushup(int rt) { sum[rt]=max(sum[rt*2],sum[rt*2+1]); } void pushdown(int rt) { if(lazy[rt]){ lazy[rt<<1]+=lazy[rt]; lazy[rt<<1|1]+=lazy[rt]; sum[rt<<1]+=lazy[rt]; sum[rt<<1|1]+=lazy[rt]; lazy[rt]=0; } } void build(int l,int r,int rt) { lazy[rt]=0; if(l==r){ sum[rt]=dis[Rev[l]]; return ; } int mid=(l+r)/2; build(l,mid,rt*2); build(mid+1,r,rt*2+1); pushup(rt); } void update(int L,int R,int w,int l,int r,int rt)//[L,R]区间加上w { if(L<=l&&R>=r){ sum[rt]+=w; lazy[rt]+=w; return ; } pushdown(rt); int mid=(l+r)>>1; if(L<=mid)update(L,R,w,l,mid,rt<<1); if(R>=mid+1)update(L,R,w,mid+1,r,rt<<1|1); pushup(rt); } ll querymax(int L,int R,int l,int r,int rt) { if(L<=l&&R>=r){ return sum[rt]; } pushdown(rt); ll ans=-INF; int mid=(l+r)>>1; if(L<=mid)ans=max(ans,querymax(L,R,l,mid,rt<<1)); if(R>=mid+1)ans=max(ans,querymax(L,R,mid+1,r,rt<<1|1)); return ans; } int main() { int T,k=1; scanf("%d",&T); while(T--){ cnt=tot=0; scanf("%d%d",&n,&m); memset(head,-1,sizeof(head)); for(int i=1;i<=n-1;i++){ int u,v; scanf("%d%d",&u,&v); u++; v++; add(u,v); add(v,u); } for(int i=1;i<=n;i++)scanf("%lld",&w[i]); dis[1]=w[1]; DFS(1,-1); build(1,n,1); printf("Case #%d:\n", k++); while(m--){ int op,x,y; scanf("%d%d",&op,&x); x++; if(op==1){ printf("%lld\n",querymax(Start[x],End[x],1,n,1)); } else{ scanf("%d",&y); update(Start[x],End[x],y-w[x],1,n,1); w[x]=y; } } } return 0; }
标签:amp printf names ons 就是 输入数据 typedef put 提交
原文地址:https://www.cnblogs.com/cherish-lin/p/11274509.html