河南企业网站建设,做外贸网站好的公司,软件设计开发,服务提供网站正题
题目链接:http://www.ybtoj.com.cn/problem/763 题目大意
给出nnn个点的一棵树#xff0c;每个di0d_i0di0的点每秒会产生一个士兵往根节点走#xff0c;走到一个节点让一个节点did_idi减一#xff08;为000就不管#xff09;。
求需要多久才能让所有点的ddd值变…正题
题目链接:http://www.ybtoj.com.cn/problem/763 题目大意
给出nnn个点的一棵树每个di0d_i0di0的点每秒会产生一个士兵往根节点走走到一个节点让一个节点did_idi减一为000就不管。
求需要多久才能让所有点的ddd值变为000
1≤n≤105,1≤di≤1081\leq n\leq10^5,1\leq d_i\leq 10^81≤n≤105,1≤di≤108 解题思路
考虑求出每个点did_idi值变成000的时间tit_iti。
对于一个节点xxxdisxdis_xdisx表示根节点到xxx的距离那么它在时刻TTT时的减少数量是 ∑y∈subtreexmax{T−ty−disydisx,0}\sum_{y\in subtree_x}max\{T-t_y-dis_ydis_x,0\}y∈subtreex∑max{T−ty−disydisx,0} 我们可以每次把新得到的ty−disyt_y-dis_yty−disy压入线段树然后每次合并上去后再在线段树上面二分出答案。
时间复杂度O(nlogn)O(n\log n)O(nlogn) code
#includecstdio
#includecstring
#includealgorithm
#define ll long long
using namespace std;
const ll N1e510,inf2e8;
struct node{ll to,next,w;
}a[N1];
ll n,tot,cnt,ans,ls[N],d[N],t[N],rt[N],dep[N];
void addl(ll x,ll y,ll w){a[tot].toy;a[tot].nextls[x];ls[x]tot;a[tot].ww;return;
}
struct SegTree{ll w[N6],c[N6],ls[N6],rs[N6];void Change(ll x,ll L,ll R,ll pos){if(!x)xcnt;w[x]pos;c[x];if(LR)return;ll mid(LR)1;if(posmid)Change(ls[x],L,mid,pos);else Change(rs[x],mid1,R,pos);return;}ll Ask(ll x,ll L,ll R,ll k,ll zc,ll zw){if(LR)return L;ll mid(LR)1,tmpmid*(c[ls[x]]zc)-w[ls[x]]-zw;if(tmpk)return Ask(ls[x],L,mid,k,zc,zw);return Ask(rs[x],mid1,R,k,zcc[ls[x]],zww[ls[x]]);}ll Merge(ll x,ll y,ll l,ll r){if(!x||!y)return xy;w[x]w[x]w[y];c[x]c[x]c[y];if(lr)return x;ll mid(lr)1;ls[x]Merge(ls[x],ls[y],l,mid);rs[x]Merge(rs[x],rs[y],mid1,r);return x;}
}T;
void dfs(ll x,ll fa){for(ll ils[x];i;ia[i].next){ll ya[i].to;if(yfa)continue;dep[y]dep[x]a[i].w;dfs(y,x);rt[x]T.Merge(rt[x],rt[y],0,inf);}t[x]max(0ll,T.Ask(rt[x],0,inf,d[x],0,0)-dep[x]);T.Change(rt[x],0,inf,t[x]dep[x]);ansmax(ans,t[x]);return;
}
signed main()
{
// freopen(conquer.in,r,stdin);
// freopen(conquer.out,w,stdout);scanf(%lld,n);for(ll i1;in;i)scanf(%lld,d[i]);for(ll i1;in;i){ll x,y,w;scanf(%lld%lld%lld,x,y,w);addl(x,y,w);addl(y,x,w);}dfs(1,1);printf(%lld\n,ans);return 0;
}