• uoj418


    题意

    uoj

    做法

    下面考虑算(ans_1),也就是全局

    将操作拍成一个序列,一个显然的贪心是放(w_i)后取出(sumlimits_{vin son_i}w_v),相当于到一个点(i)时,(A_i=+w_i-sumlimits_{vin son_i}w_v),求最大前缀和

    这样会发生一个问题,就是怎么构造这个序列,先选完儿子才能选父亲,很不好搞

    这样转换:把操作序列倒过来看,就是先选父亲,才能选儿子节点。
    之前比如在相对序列中儿子值的变化:({son_1(+w_{1}),...,son_2(+w_{2}),...,son_3(+w_3),...fa(-w_1-w_2-w_3)})
    现在等价于:({fa(+w_1+w_2+w_3)},...,son_3(-w_3),...,son_2(-w_2),...,son_1(-w_1))
    对于序列上的某个点(i),定义二元组((+sumlimits_{vin son_i}w_v-w_i,+sumlimits_{vin son_i}w_v))表示经过该点后的增量、历史最大增量

    合并是显然的:((x,y)+(x',y')=(x+x',max(y,x+y')))

    然后这样的二元组是有严格的优先级的:

    • (x<0)的,优先放前面;多个(x<0)的,(y)较小的放前面
    • ((x,y),(x',y')(x,x'>0))((x,y))放前面当且仅当:(max(y,x+y')<max(y',x'+y)),由于(x,x'>0),等价于(x+y'<x'+yLongrightarrow x-y<x'-y')

    做全局解后,显然某个子树的解序列是全局解的子序列,如果我们能得到全局解序列,那么通过线段树合并容易计算每个点的答案

    然后贪心的做这个:
    当取出的点(i)其父亲还没取出来时,令其与父亲合并
    我们需要得到全局解,要用链表维护

    Code

    上面讲的可能有点不清楚,放份代码帮助理解一下

    #include<bits/stdc++.h>
    typedef long long LL;
    #define pb push_back
    #define opt operator
    #define pii std::pair<LL,LL>
    const LL maxn=2e5+9;
    LL Read(){
    	LL x(0),f(1); char c=getchar();
    	while(c<'0' || c>'9'){
    		if(c=='-') f=-1; c=getchar();
    	}
    	while(c>='0' && c<='9'){
    		x=(x<<3ll)+(x<<1ll)+c-'0'; c=getchar();
    	}return x*f;
    }
    namespace Uf{
    	LL fa[maxn];
    	void Init(LL N){
    		for(LL i=1;i<=N;++i) fa[i]=i;
    	}
    	LL Find(LL x){
    		return fa[x]==x?x:fa[x]=Find(fa[x]);
    	}
    }
    struct node{
    	LL x,y,id;
    	bool opt < (const node A)const{
    		if(x<0 && A.x>=0) return 1;
    		if(A.x<0 && x>=0) return 0;
    		if(x<0 && A.x<0){
    			return (y<A.y || (y==A.y && id<A.id));
    		}
    		LL xx(y-x),yy(A.y-A.x);
    		return (xx>yy || (xx==yy && id<A.id));
    	}
    	node opt + (const node A)const{
    		return (node){x+A.x,std::max(y,x+A.y),id};
    	}
    };
    namespace Sgt{
    	LL nod;
    	LL rt[maxn],son[maxn*20][2];
    	node val[maxn*20];
        void Modify(LL &nw,LL l,LL r,LL x,node v){
    		nw=++nod; val[nw]=v;
    		if(l==r){
    			return;
    		}
    		LL mid(l+r>>1);
    		if(x<=mid) Modify(son[nw][0],l,mid,x,v);
    		else Modify(son[nw][1],mid+1,r,x,v);
    	}
    	LL Merge(LL x,LL y){
    		if(!x || !y) return x|y;
    		son[x][0]=Merge(son[x][0],son[y][0]);
    		son[x][1]=Merge(son[x][1],son[y][1]);
    		val[x]=val[son[x][0]]+val[son[x][1]];
    		return x;
    	}
    }
    LL n,tot,T;
    LL ans[maxn],val[maxn],w[maxn],nxt[maxn],head[maxn],tail[maxn],vis[maxn];
    LL pos[maxn],fa[maxn];
    node a[maxn];
    std::vector<LL> V[maxn];
    void Dfs(LL u){
    	Sgt::Modify(Sgt::rt[u],1,n,pos[u],(node){val[u]-w[u],val[u]});
    	for(LL i=0;i<V[u].size();++i){
    		LL v(V[u][i]);
    		Dfs(v);
    		Sgt::rt[u]=Sgt::Merge(Sgt::rt[u],Sgt::rt[v]);
    	}
    	ans[u]=Sgt::val[Sgt::rt[u]].y+w[u];
    }
    std::set<node> Set;
    std::set<node>::iterator it1;
    void Init(){
    	for(LL i=1;i<=n;++i){
    		val[fa[i]]+=w[i];
    	}
    	for(LL i=1;i<=n;++i){
    		a[i]=(node){val[i]-w[i],val[i],i};
    		Set.insert(a[i]);
    		head[i]=i; tail[i]=i;
    	}
    	Uf::Init(n);
    }
    void Update(LL u){
    	LL x(head[u]);
    	while(x){
    		++tot; pos[x]=tot;
    		vis[x]=1;
    		x=nxt[x];
    	}
    }
    void Merge(LL f,LL u){
    	Uf::fa[u]=f;
    	nxt[tail[f]]=head[u];
    	tail[f]=tail[u];
    	it1=Set.find(a[f]); Set.erase(it1);
    	a[f]=a[f]+a[u];
    	Set.insert(a[f]);
    }
    void Solve(){
    	memset(vis,0,sizeof(vis));
    	vis[0]=1;
    	while(!Set.empty()){
    		it1=Set.begin(); Set.erase(it1);
    		LL u((*it1).id),f(Uf::Find(fa[u]));
    		if(vis[f]){
    			Update(u);
    		}else{
    			Merge(f,u);
    		}
    	}
    }
    int main(){
    	T=Read();
    	n=Read();
    	for(LL i=2;i<=n;++i){
    		LL x(Read());
    		fa[i]=x; V[x].pb(i);
    	}
        for(LL i=1;i<=n;++i){
    		w[i]=Read();
    	}
    	Init();
    	Solve();
    	Dfs(1);
    	for(LL i=1;i<=n;++i) printf("%lld ",ans[i]);
    	puts("");
    	return 0;
    }
    
  • 相关阅读:
    MyEclipse10.7 10.6导出war文件报错 “SECURITY ALERT: INTEGERITY CHECK ERROR”
    基于ssh框架的highcharts前后台数据交互实例
    java自定义注解知识实例及SSH框架下,拦截器中无法获得java注解属性值的问题
    新特性:postgresql的vacuum漫谈
    postgresql vacuum操作
    __declspec(dllexport) 的意思与DEF导出函数的区别(转)
    一个睡五分钟等于六个钟头的方法(转)
    【转】应届毕业生要知道的几个小东西,,三方协议,,报到证,,干部身份
    测试word客户端发布Blog
    66句震撼人心的禅语(转)
  • 原文地址:https://www.cnblogs.com/Grice/p/12822602.html
Copyright © 2020-2023  润新知