传送门

好迷啊……膜一下ljz

考虑每个操作,如果把操作按先后顺序放到序列上的话,操作一就是把\(w_i\)的石子放到某个节点,那么就是在序列末端加入\(w_i\),然后根据贪心肯定要把它所有儿子的石子拿走,也就是要减去\(\sum w_{son}\)

那么每个点的答案就是序列的最大前缀

因为父亲节点的操作一要在儿子之后进行,很麻烦,那么可以每次在自己这里把\(w_i\)减掉,到父亲的时候再加回去

记\((x,y)\)为一个二元组,\(x\)表示当前位置的最大前缀和,\(y\)表示最小后缀和,然后定义一个运算\((ax,by)=(x+max(0,a+y),b+min(0,a+y)\),大概能看出是个什么东西,注意这个运算不满足交换律

然后考虑一下这些二元组在序列中的顺序,如果\(x+y<0\),那么肯定得放前面,因为可以让之后的前缀和减小。

那么当\(x+y<0\)时,按\(x\)排序,这样能使前缀和不断减小。如果\(x+y>0\),按\(y\)排序就好了

维护二元组的话,用线段树合并,如果当前二元组的\(x+y<0\)且有比它最大前缀大的二元组,那么就已经是最优的了否则将在它前面的二元组与它合并,合并完后加进线段树里就好了。注意合并完之后节点没了要记得清空

//minamoto
#include<bits/stdc++.h>
#define R register
#define int long long
#define loli 200000000000000
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++C]=z[Z],--Z);sr[++C]=' ';
}
const int N=4e5+5;
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
struct node{
int mx,mn;
node(){}
node(R int mx,R int mn):mx(mx),mn(mn){}
inline node operator +(const node &b){return node(mx+max(0ll,mn+b.mx),b.mn+min(0ll,mn+b.mx));}
}tr[N<<5];
int w[N],rt[N],ans[N],ls[N<<5],rs[N<<5];
int n,cnt,fa;
void ins(int &p,int l,int r,node x){
if(!p)p=++cnt;if(l==r)return (void)(tr[p]=tr[p]+x);
int mid=(l+r)>>1;
x.mx<=mid?ins(ls[p],l,mid,x):ins(rs[p],mid+1,r,x);
tr[p]=tr[ls[p]]+tr[rs[p]];
}
int merge(int x,int y,int l,int r){
if(!x||!y)return x|y;if(l==r)return tr[x]=tr[x]+tr[y],x;
int mid=(l+r)>>1;
ls[x]=merge(ls[x],ls[y],l,mid),rs[x]=merge(rs[x],rs[y],mid+1,r);
tr[x]=tr[ls[x]]+tr[rs[x]];
return x;
}
void update(int &p,int l,int r,node &x,bool &flag){
if(!p||flag)return;
if(l==r){
if(x.mx+x.mn<0&&x.mx<l)return (void)(flag=1);
x=x+tr[p],p=0;return;
}
int mid=(l+r)>>1;
update(ls[p],l,mid,x,flag),update(rs[p],mid+1,r,x,flag);
if(ls[p]||rs[p])tr[p]=tr[ls[p]]+tr[rs[p]];
else p=0;
}
void dfs(int u){
node res=node(0,-w[u]);
go(u){
res.mx+=w[v],dfs(v);
rt[u]=merge(rt[u],rt[v],0,loli);
}
node qaq=res;bool flag=0;
qaq.mx+=w[u],ans[u]=(qaq+tr[rt[u]]).mx;
update(rt[u],0,loli,res,flag),ins(rt[u],0,loli,res);
}
signed main(){
// freopen("testdata.in","r",stdin);
read(),n=read();
fp(i,2,n)fa=read(),add(fa,i);
fp(i,1,n)w[i]=read();
dfs(1);
fp(i,1,n)print(ans[i]);
return Ot(),0;
}

uoj#418. 【集训队作业2018】三角形(线段树合并)的更多相关文章

  1. uoj #450[集训队作业2018]复读机

    传送门 \(d=1\),那么任何时刻都可以\(k\)个复读机的一种,答案为\(k^n\) \(d>1\),可以枚举某个复读机的复读次数(必须是\(d\)的倍数),然后第\(i\)个复读时间为\( ...

  2. UOJ 422 [集训队作业2018] 小Z的礼物 min-max容斥 期望 轮廓线dp

    LINK:小Z的礼物 太精髓了 我重学了一遍min-max容斥 重写了一遍按位或才写这道题的. 还是期望多少时间可以全部集齐. 相当于求出 \(E(max(S))\)表示最后一个出现的期望时间. 根据 ...

  3. UOJ#418. 【集训队作业2018】三角形

    #418. [集训队作业2018]三角形 和三角形没有关系 只要知道儿子放置的顺序,就可以直接模拟了 记录历史最大值 用一个pair(a,b):之后加上a个,期间最大值为增加b个 合并? A1+A2= ...

  4. UOJ #449. 【集训队作业2018】喂鸽子

    UOJ #449. [集训队作业2018]喂鸽子 小Z是养鸽子的人.一天,小Z给鸽子们喂玉米吃.一共有n只鸽子,小Z每秒会等概率选择一只鸽子并给他一粒玉米.一只鸽子饱了当且仅当它吃了的玉米粒数量\(≥ ...

  5. 【UOJ#450】【集训队作业2018】复读机(生成函数,单位根反演)

    [UOJ#450][集训队作业2018]复读机(生成函数,单位根反演) 题面 UOJ 题解 似乎是\(\mbox{Anson}\)爷的题. \(d=1\)的时候,随便怎么都行,答案就是\(k^n\). ...

  6. 【UOJ#422】【集训队作业2018】小Z的礼物(min-max容斥,轮廓线dp)

    [UOJ#422][集训队作业2018]小Z的礼物(min-max容斥,轮廓线dp) 题面 UOJ 题解 毒瘤xzy,怎么能搬这种题当做WC模拟题QwQ 一开始开错题了,根本就不会做. 后来发现是每次 ...

  7. [集训队作业2018]蜀道难——TopTree+贪心+树链剖分+链分治+树形DP

    题目链接: [集训队作业2018]蜀道难 题目大意:给出一棵$n$个节点的树,要求给每个点赋一个$1\sim n$之内的权值使所有点的权值是$1\sim n$的一个排列,定义一条边的权值为两端点权值差 ...

  8. UOJ418. 【集训队作业2018】三角形

    http://uoj.ac/problem/418 题解 考虑激活每个节点时,它的每个儿子都是放满的. 那每一次的操作我们可以用一个二元组来表示\((w_i-\sum w_{son},\sum w_{ ...

  9. UOJ#428. 【集训队作业2018】普通的计数题

    #428. [集训队作业2018]普通的计数题 模型转化好题 所以变成统计有标号合法的树的个数. 合法限制: 1.根标号比子树都大 2.如果儿子全是叶子,数量B中有 3.如果存在一个儿子不是叶子,数量 ...

随机推荐

  1. bootstrap-table 行内编辑

    1.文件引入 <link rel="stylesheet" href="bootstrap.css"> <link rel="sty ...

  2. 在yum出问题的情况下安装某个rpm包的方法

    1 核心命令 rpm -i 2 方法 centos镜像站去找到所有的rpm包. 安装这个rpm包,发现有一个依赖没有安装,就去下载安装.因为整体的包是有限的,因此终会收敛的. 比如安装rpmbuild ...

  3. 原来浏览器原生支持JS Base64编码解码 outside of the Latin1 range

    原来浏览器原生支持JS Base64编码解码 « 张鑫旭-鑫空间-鑫生活 https://www.zhangxinxu.com/wordpress/2018/08/js-base64-atob-bto ...

  4. Nothing but the key 属性全部依赖于主键 third norm form

    全依赖 Designs that Violate 1NF CustomerCustomer ID First Name Surname Telephone Number123 Pooja Singh ...

  5. android studio发布公共类库到服务器maven仓库

    在上一篇中提到了怎么创建私有maven库,这篇主要结合android studio的使用,直接进入正题,看以下步骤 1.创建android项目 创建Project,然后加一个library的modul ...

  6. MongoDB 学习三

    这章我们学习MongoDB的查询操作. Introduction to find find方法用于执行MongoDB的查询操作.它返回collecion中的documents子集,没有添加参数的话它将 ...

  7. 高速排序及优化(Java版)

    高速排序(Quicksort)是对冒泡排序的一种改进. 高速排序由C. A. R. Hoare在1962年提出. 一次高速排序具体过程: 选择数组第一个值作为枢轴值. 代码实现: package Qu ...

  8. hdu1198 Farm Irrigation —— dfs or 并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1198 dfs: #include<cstdio>//hdu1198 dfs #includ ...

  9. 51Nod - 1295:XOR key (可持久化Trie求区间最大异或)

    给出一个长度为N的正整数数组A,再给出Q个查询,每个查询包括3个数,L, R, X (L <= R).求ALL 至 ARR 这R - L + 1个数中,与X 进行异或运算(Xor),得到的最大值 ...

  10. jquery的跨域请求

    项目中关于ajax jsonp的使用,出现了问题:可以成功获得请求结果,但没有执行success方法总算搞定了,记录一下 function TestAjax() {    $.ajax({       ...