ICode9

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

CF1178G The Awesomest Vertex

2022-08-11 16:32:39  阅读:124  来源: 互联网

标签:Awesomest const int tree sum Vertex long CF1178G maxn


前言

思维量还可以(也挺大的)但是代码量巨大(写起来特别不舒服)的又一道神仙题。

正文

题目大意:一棵树 \(n\) 个节点,以 \(1\) 为根,每个节点有两个属性 \((a,b)\),\(R(v)\) 为 \(v\) 的祖先(包括自己):

\[|\sum_{u\in R(v)}a_u|\cdot|\sum_{u\in R(v)}b_u| \]

需要支持:

  • 将 \(a_v\) 加上 \(x\)。
  • 查询 \(v\) 的子树里最大值。

数据范围:\(n\leq 2\cdot 10^5,q\leq 10^5\)

思路比较简单。

考虑将 \(|\sum a|\) 拆成 \(\max(\sum a,-\sum a)\),\(b_i\) 可以预处理。

然后你看到柿子形式 \(\Delta x\cdot b+ab\) 直接斜率优化维护凸壳。

凸壳放在线段树里合并即可。

主要还是代码难写QAQ。

#include <bits/stdc++.h>
#define sz(x) (int)(x.size())
using namespace std;
const int mod=1e9+7,Base=233,inf=0x3f3f3f3f;
const long long INF=0x3f3f3f3f3f3f3f3f;
template<typename T>inline void chmax(T &a, T b){a=max(a,b);}
template<typename T>inline void chmin(T &a, T b){a=min(a,b);}
inline void trans(int &a,int b){a+=b;if(a>mod)a-=mod;}
const int maxn=4e5+5;
int n,q,p[maxn];
long long a[maxn],b[maxn];
vector<int> g[maxn];
int in[maxn],out[maxn],tim=0;
long long ne[maxn<<2],d[maxn<<2];
struct line
{
	long long k,b;
}val[maxn];
struct node
{
	int l,r;
	long long k,b;
};
struct segtree
{
	node tree[maxn<<2];
	void pushup(int x)
	{
		int v=(tree[x<<1].b>=tree[x<<1|1].b?(x<<1):(x<<1|1));
		tree[x].k=tree[v].k;
		tree[x].b=tree[v].b;
		ne[x]=min((tree[v].k>=tree[v^1].k?INF:(tree[v].b-tree[v^1].b)/(tree[v^1].k-tree[v].k)),min(ne[x<<1],ne[x<<1|1]));
	}
	void upd(int x,long long v)
	{
		tree[x].b+=tree[x].k*v;
		ne[x]-=v;
		d[x]+=v;
	}
	void pushdown(int x)
	{
		if(!d[x])
			return;
		upd(x<<1,d[x]);
		upd(x<<1|1,d[x]);
		d[x]=0;
	}
	void build(int x,int l,int r)
	{
		tree[x].l=l;
		tree[x].r=r;
		if(l==r)
		{
			tree[x].k=val[l].k;
			tree[x].b=val[l].b; 
			ne[x]=INF;
			return;
		}
		int mid=(l+r)>>1;
		build(x<<1,l,mid);
		build(x<<1|1,mid+1,r);
		pushup(x);
	}
	void update(int x,int l,int r,long long v)
	{
		if(!tree[x].r)
			return;
		if(tree[x].l>=l&&tree[x].r<=r&&v<=ne[x])
		{
			upd(x,v);
			return; 
		}
		pushdown(x);
		int mid=(tree[x].l+tree[x].r)>>1;
		if(l<=mid)
			update(x<<1,l,r,v);
		if(r>mid)
			update(x<<1|1,l,r,v);
		pushup(x);
	}
	long long query(int x,int l,int r)
	{
		if(tree[x].l>=l&&tree[x].r<=r)
			return tree[x].b;
		pushdown(x);
		int mid=(tree[x].l+tree[x].r)>>1;
		long long ret=-INF;
		if(l<=mid)
			ret=query(x<<1,l,r);
		if(r>mid)
			chmax(ret,query(x<<1|1,l,r));
		return ret;
	}
}tr;
void dfs(int u)
{
	in[u]=++tim;
	a[u]+=a[p[u]];
	b[u]+=b[p[u]];
	long long v=abs(b[u]);
	val[tim]={v,a[u]*v};
	for(int i=0;i<sz(g[u]);i++)
	{
		int v=g[u][i];
		dfs(v);
	}
	out[u]=++tim;
	val[tim]={-v,-a[u]*v};
}
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=2;i<=n;i++)
	{
		scanf("%d",p+i);
		g[p[i]].push_back(i);
	}
	for(int i=1;i<=n;i++)
		scanf("%lld",a+i);
	for(int i=1;i<=n;i++)
		scanf("%lld",b+i);
	dfs(1);
	tr.build(1,1,tim);
	int opt,v;
	long long x;
	while(q--)
	{
		scanf("%d%d",&opt,&v);
		if(opt==1)
		{
			scanf("%lld",&x);
			tr.update(1,in[v],out[v],x);
		}
		else
		{
			printf("%lld\n",tr.query(1,in[v],out[v]));
		}
	}
    return 0;
}

标签:Awesomest,const,int,tree,sum,Vertex,long,CF1178G,maxn
来源: https://www.cnblogs.com/Jerry-Jiang/p/16576448.html

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

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

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

ICode9版权所有