ICode9

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

CF1303G - Sum of Prefix Sums

2021-05-23 11:03:23  阅读:149  来源: 互联网

标签:rt Node int Sum Sums dep dfn CF1303G ll


CF1303G - Sum of Prefix Sums

题目大意

定义一个数列的\(a_1,a_2,\cdots a_n\)的权值为\(\sum (n-i+1)a_i\)

对于一棵带点权的树,求所有路径数列最大的权值


分析

首先对于路径问题可以考虑无脑树分治

假设确定一条路径到达根的\(b_1,b_2,\cdots b_m\),一条从根出发的路径\(c_1,c_2,\cdots c_k\)

设\(s_1=\sum (m-i+1)b_i,s_2=\sum b_i\),\(s_3=\sum (k-i+1)c_i\)

则易知其贡献为\(s_1+s2\cdot k+s_3\)

考虑这是一个斜率优化的形式,可以通过凸包维护

但是不同的实现方法有很多,复杂度为基本上都是\(O(n\log ^2n)\)

比如:

1.点分治+分治合并凸包+分治合并查询

2.点分治+李超树

3.边分治+凸包(需要\(sort\),说不定不用?)

我无脑李超树

const int N=2e5+10,INF=1e9+10;

int n,m,a[N];
vector <int> G[N];
struct Node{
	ll k,b;
	Node(){}
	Node(ll k,ll b):k(k),b(b){}
	ll operator [] (ll x) const { return k*x+b; }
} s[N];
int ls[N],rs[N],cnt;
int New(){
	int u=++cnt;
	ls[u]=rs[u]=0,s[u]=Node(-INF,-INF);
	return u;
}
void Upd(int &p,int l,int r,Node x){
	if(x.k<0) return;
	if(!p) p=New();
	int mid=(l+r)>>1;
	if(s[p][mid]<x[mid]) swap(s[p],x);
	if(l==r) return;
	if(x[l]>s[p][l]) Upd(ls[p],l,mid-1,x);
	if(x[r]>s[p][r]) Upd(rs[p],mid+1,r,x);
}
ll Que(int p,int l,int r,int x){
	if(l==r) return s[p][x];
	int mid=(l+r)>>1;
	return max(s[p][x],x<=mid?Que(ls[p],l,mid,x):Que(rs[p],mid+1,r,x));
}

int vis[N],mi=1e9,rt,sz[N];
void FindRt(int n,int u,int f){
	int ma=0; sz[u]=1;
	for(int v:G[u]) if(v!=f && !vis[v]) {
		FindRt(n,v,u);
		cmax(ma,sz[v]),sz[u]+=sz[v];
	}
	cmax(ma,n-sz[u]);
	if(mi>ma) mi=ma,rt=u;
}

ll s1[N],s2[N],s3[N],s4[N],dep[N];
int L[N],I[N],dfn,R[N];
void dfs(int u,int f){
	dep[u]=dep[f]+1;
	s2[u]=s2[f]+a[u],s1[u]=s1[f]+1ll*a[u]*(dep[u]+1);
	s4[u]=s4[f]+a[u],s3[u]=s3[f]+s4[u];
	I[L[u]=++dfn]=u;
	for(int v:G[u]) if(v!=f && !vis[v]) dfs(v,u);
	R[u]=dfn;
}
ll ans;
void Div(int n,int u){
	mi=1e9,FindRt(n,u,0),vis[u=rt]=1;
	s1[u]=s2[u]=a[u],s3[u]=s4[u]=dep[u]=0;
	
	I[L[u]=dfn=1]=u;
	for(int v:G[u]) if(!vis[v]) dfs(v,u);
	R[u]=dfn;

	cmax(ans,(ll)a[u]),cnt=rt=0;
	Upd(rt,1,dfn,Node(s2[u],s1[u]));
	for(int v:G[u]) if(!vis[v]) {
		rep(j,L[v],R[v]) {
			int i=I[j];
			cmax(ans,Que(rt,1,dfn,dep[i])+s3[i]);
		}
		rep(j,L[v],R[v]) {
			int i=I[j];
			Upd(rt,1,dfn,Node(s2[i],s1[i]));
		}
	}
	cnt=rt=0;
	drep(k,G[u].size()-1,0) {
		int v=G[u][k];
		if(vis[v]) continue;
		rep(j,L[v],R[v]) {
			int i=I[j];
			cmax(ans,Que(rt,1,dfn,dep[i])+s3[i]);
		}
		rep(j,L[v],R[v]) {
			int i=I[j];
			Upd(rt,1,dfn,Node(s2[i],s1[i]));
		}
	}
	cmax(ans,Que(rt,1,dfn,dep[u])+s3[u]);
	for(int v:G[u]) if(!vis[v]) {
		if(sz[v]>sz[u]) sz[v]=n-sz[u];
		Div(sz[v],v);
	}
}

int main(){
	s[0]=Node(-1,-INF);
	n=rd();
	rep(i,2,n) {
		int u=rd(),v=rd();
		G[u].pb(v),G[v].pb(u);
	}
	rep(i,1,n) a[i]=rd();
	Div(n,1);
	printf("%lld\n",ans);
}

标签:rt,Node,int,Sum,Sums,dep,dfn,CF1303G,ll
来源: https://www.cnblogs.com/chasedeath/p/14800644.html

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

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

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

ICode9版权所有