zoukankan      html  css  js  c++  java
  • 【CF1303G】Sum of Prefix Sums(点分治+李超线段树)

    点此看题面

    • 一棵(n)个点的树,第(i)个点权值为(a_i)
    • 假设一条路径上的点权依次为(b_{1sim k}),则这条路径的权值为(sum_{i=1}^ki imes b_i)
    • 对于所有树上路径,求出其中最大的权值。
    • (nle1.5 imes10^5,a_ile10^6)

    点分治+李超线段树

    对于这种询问范围为所有树上路径问题,很容易想到点分治。

    核心问题是如何合并两条路径。

    假设一条从下往上到当前根的路径点数为(c_1),权值为(s_1);一条由当前根从上往下的路径点权和为(t_2),权值为(s_2)。那么这两条路径合并后的权值就是(s_1+s_2+c_1 imes t_2)

    也就是说,每条从上往下的路径可以看作一个一次函数(t_2x+s_2),而对于每条从下往上的路径我们询问(x=c_1)时的最大(y)值再加上(s_1)更新答案。

    显然可以套用李超线段树解决。

    代码:(O(nlog^2n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Rg register
    #define RI Rg int
    #define Cn const
    #define CI Cn int&
    #define I inline
    #define W while
    #define N 150000
    #define V 150000000000LL
    #define LL long long
    #define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
    using namespace std;
    int n,a[N+5],ee,lnk[N+5];struct edge {int to,nxt;}e[N<<1];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	char oc,FI[FS],*FA=FI,*FB=FI;
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    }using namespace FastIO;
    struct Seg
    {
    	LL k,b;I Seg(Cn LL& x=0,Cn LL& y=0):k(x),b(y){}
    	I LL operator () (Cn LL& x) Cn {return k*x+b;}
    };
    class SegmentTree
    {
    	private:
    		#define PT CI l=1,CI r=n,CI rt=1
    		#define LT l,mid,rt<<1
    		#define RT mid+1,r,rt<<1|1
    		Seg P[N<<2];
    	public:
    		I void Cl(PT) {if(!P[rt].k) return;if(P[rt]=Seg(),l==r) return;RI mid=l+r>>1;Cl(LT),Cl(RT);}//清空
    		I LL Q(CI x,PT) {RI mid=l+r>>1;return P[rt].k?max(l^r?(x<=mid?Q(x,LT):Q(x,RT)):0,P[rt](x)):0;}//询问x处的最大y值
    		I void A(Seg s,PT)//加入一条线段
    		{
    			if(!P[rt].k) return (void)(P[rt]=s);RI mid=l+r>>1;s(mid)>P[rt](mid)&&(swap(s,P[rt]),0);//记录较优的线段
    			if(l==r) return;s(l)>P[rt](l)&&(A(s,LT),0),s(r)>P[rt](r)&&(A(s,RT),0);//进入未被完全碾压的子区间
    		}
    }S;
    namespace T//点分治
    {
    	int u[N+5];LL ans;
    	int rt,Sz[N+5],Mx[N+5];I void GetRt(CI x,CI lst,RI sz)//找重心
    	{
    		Sz[x]=1,Mx[x]=0;for(RI i=lnk[x];i;i=e[i].nxt) !u[e[i].to]&&
    			e[i].to^lst&&(GetRt(e[i].to,x,sz),Sz[x]+=Sz[e[i].to],Mx[x]=max(Mx[x],Sz[e[i].to]));
    		(Mx[x]=max(Mx[x],sz-Sz[x]))<Mx[rt]&&(rt=x);
    	}
    	I void U(CI x,CI lst,RI c,LL t,LL s)//从上往下的路径
    	{
    		S.A(Seg(t+=a[x],s+=1LL*(++c)*a[x]));//把这个一次函数修加到线段树上
    		for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&!u[e[i].to]&&(U(e[i].to,x,c,t,s),0);
    	}
    	I void Q(CI x,CI lst,RI c,LL t,LL s)//从下往上的路径
    	{
    		++c,s+=(t+=a[x]),ans=max(ans,S.Q(c)+s);//在线段树上询问
    		for(RI i=lnk[x];i;i=e[i].nxt) e[i].to^lst&&!u[e[i].to]&&(Q(e[i].to,x,c,t,s),0);
    	}
    	int T,St[N+5];I void Solve(RI x)//点分治
    	{
    		RI i;for(u[x]=1,S.Cl(),i=lnk[x];i;i=e[i].nxt) !u[e[i].to]&&//正着搞一遍,最后考虑当前根
    			(Q(St[++T]=e[i].to,x,1,a[x],a[x]),U(e[i].to,x,0,0,0),0);ans=max(ans,S.Q(1)+a[x]);
    		S.Cl(),S.A(Seg(a[x],a[x]));W(T) Q(St[T],x,0,0,0),U(St[T--],x,1,a[x],a[x]);//反着搞一遍,首先插入当前根
    		for(i=lnk[x];i;i=e[i].nxt) !u[e[i].to]&&(GetRt(e[i].to,rt=0,Sz[e[i].to]),Solve(rt),0);//进入分治子树
    	}
    }
    int main()
    {
    	RI i,x,y;for(read(n),i=1;i^n;++i) read(x,y),add(x,y),add(y,x);for(i=1;i<=n;++i) read(a[i]);
    	using namespace T;return Mx[0]=1e9,GetRt(1,rt=0,n),Solve(rt),printf("%lld
    ",ans),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    Luogu 1080 【NOIP2012】国王游戏 (贪心,高精度)
    Luogu 1314 【NOIP2011】聪明的质检员 (二分)
    Luogu 1315 【NOIP2011】观光公交 (贪心)
    Luogu 1312 【NOIP2011】玛雅游戏 (搜索)
    Luogu 1525 【NOIP2010】关押罪犯 (贪心,并查集)
    Luogu 1514 引水入城 (搜索,动态规划)
    UVA 1394 And Then There Was One / Gym 101415A And Then There Was One / UVAlive 3882 And Then There Was One / POJ 3517 And Then There Was One / Aizu 1275 And Then There Was One (动态规划,思维题)
    Luogu 1437 [HNOI2004]敲砖块 (动态规划)
    Luogu 1941 【NOIP2014】飞扬的小鸟 (动态规划)
    HDU 1176 免费馅饼 (动态规划)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/CF1303G.html
Copyright © 2011-2022 走看看