zoukankan      html  css  js  c++  java
  • CF1303G

    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+s2cdot k+s_3)

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

    但是不同的实现方法有很多,复杂度为基本上都是(O(nlog ^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
    ",ans);
    }
    
  • 相关阅读:
    .net com
    Json树递归Js查询Json父子节点
    Angular中使用$watch监听object属性值的变化
    教程
    JS格式化Thu May 12 2016 08:00:00 GMT+0800 (中国标准时间)
    js中获取时间new Date()详细介绍
    select默认空白问题。。
    angular先加载页面再执行事件,特别在动态生成id,然后做echarts等图表
    详解angularJs中自定义directive的数据交互
    Angularjs ng-table的使用(可以加button)以及angularjs学习资料
  • 原文地址:https://www.cnblogs.com/chasedeath/p/14800644.html
Copyright © 2011-2022 走看看