ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

YbtOJ#763-攻城略池【线段树合并】

2021-02-21 15:01:48  阅读:185  来源: 互联网

标签:rt return YbtOJ ll 略池 mid ls 763 dis


正题

题目链接:http://www.ybtoj.com.cn/problem/763


题目大意

给出\(n\)个点的一棵树,每个\(d_i=0\)的点每秒会产生一个士兵往根节点走,走到一个节点让一个节点\(d_i\)减一(为\(0\)就不管)。

求需要多久才能让所有点的\(d\)值变为\(0\)

\(1\leq n\leq10^5,1\leq d_i\leq 10^8\)


解题思路

考虑求出每个点\(d_i\)值变成\(0\)的时间\(t_i\)。

对于一个节点\(x\),\(dis_x\)表示根节点到\(x\)的距离,那么它在时刻\(T\)时的减少数量是

\[\sum_{y\in subtree_x}max\{T-t_y-dis_y+dis_x,0\} \]

我们可以每次把新得到的\(t_y-dis_y\)压入线段树,然后每次合并上去后再在线段树上面二分出答案。

时间复杂度\(O(n\log n)\)


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10,inf=2e8;
struct node{
	ll to,next,w;
}a[N<<1];
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].to=y;
	a[tot].next=ls[x];
	ls[x]=tot;a[tot].w=w;
	return;
}
struct SegTree{
	ll w[N<<6],c[N<<6],ls[N<<6],rs[N<<6];
	void Change(ll &x,ll L,ll R,ll pos){
		if(!x)x=++cnt;w[x]+=pos;c[x]++;
		if(L==R)return;ll mid=(L+R)>>1;
		if(pos<=mid)Change(ls[x],L,mid,pos);
		else Change(rs[x],mid+1,R,pos);
		return;
	}
	ll Ask(ll x,ll L,ll R,ll k,ll zc,ll zw){
		if(L==R)return L;
		ll mid=(L+R)>>1,tmp=mid*(c[ls[x]]+zc)-w[ls[x]]-zw;
		if(tmp>=k)return Ask(ls[x],L,mid,k,zc,zw);
		return Ask(rs[x],mid+1,R,k,zc+c[ls[x]],zw+w[ls[x]]);
	}
	ll Merge(ll x,ll y,ll l,ll r){
		if(!x||!y)return x+y;
		w[x]=w[x]+w[y];c[x]=c[x]+c[y];
		if(l==r)return x;ll mid=(l+r)>>1;
		ls[x]=Merge(ls[x],ls[y],l,mid);
		rs[x]=Merge(rs[x],rs[y],mid+1,r);
		return x;
	}
}T;
void dfs(ll x,ll fa){
	for(ll i=ls[x];i;i=a[i].next){
		ll y=a[i].to;
		if(y==fa)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]);
	ans=max(ans,t[x]);return;
}
signed main()
{
//	freopen("conquer.in","r",stdin);
//	freopen("conquer.out","w",stdout);
	scanf("%lld",&n);
	for(ll i=1;i<=n;i++)
		scanf("%lld",&d[i]);
	for(ll i=1;i<n;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;
}

标签:rt,return,YbtOJ,ll,略池,mid,ls,763,dis
来源: https://www.cnblogs.com/QuantAsk/p/14425808.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有