样例已过,蒟蒻树剖求调
查看原帖
样例已过,蒟蒻树剖求调
439177
Supor__Shoep楼主2023/1/29 17:42
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+5;
int seg[MAXN],fa[MAXN],depth[MAXN];
int son[MAXN],siz[MAXN],top[MAXN],a[MAXN];
int nowval[MAXN];
int sumdfs;
int n,m;
struct node
{
	int l,r,sum,num,lsum,rsum,Tar;
	node(){ sum=num=lsum=rsum=Tar=0; }
}tree[MAXN<<2];
int head[MAXN],nxt[MAXN<<1],to[MAXN<<1],tot;
void add(int x,int y)
{
	to[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}
void dfs1(int now,int pre)
{
	fa[now]=pre,depth[now]=depth[pre]+1,siz[now]=1;
	for(int i=head[now];i;i=nxt[i])
	{
		if(to[i]==pre)	continue;
		dfs1(to[i],now);
		siz[now]+=siz[to[i]];
		if(siz[to[i]]>siz[son[now]])	son[now]=to[i];
	}
}
void dfs2(int x,int t)
{
	seg[x]=++sumdfs,top[x]=t;
	nowval[sumdfs]=a[x];
	if(!son[x])	return;
	if(son[x])	dfs2(son[x],t);
	for(int i=head[x];i;i=nxt[i])
	{
		if(to[i]==fa[x]||to[i]==son[x])	continue;
		dfs2(to[i],to[i]);
	}
}
void pushup(int now)
{
	tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
	tree[now].lsum=max(tree[now<<1].lsum,tree[now<<1].sum+tree[now<<1|1].lsum);
	tree[now].rsum=max(tree[now<<1|1].rsum,tree[now<<1|1].sum+tree[now<<1].rsum);
	tree[now].num=max(tree[now<<1].rsum+tree[now<<1|1].lsum,max(tree[now<<1].num,tree[now<<1|1].num));
}
void build_tree(int now,int l,int r)
{
	tree[now].l=l,tree[now].r=r,tree[now].Tar=-1e5;
	if(l==r)
	{
		tree[now].lsum=tree[now].rsum=tree[now].num=tree[now].sum=nowval[l];
		return;
	}
	int mid=(l+r)/2;
	build_tree(now<<1,l,mid);
	build_tree(now<<1|1,mid+1,r);
	pushup(now);
}
void fixed_tree(int now)
{
	if(tree[now].Tar!=-1e5)
	{
		tree[now<<1].Tar=tree[now<<1|1].Tar=tree[now].Tar;
		tree[now<<1].sum=(tree[now<<1].r-tree[now<<1].l+1)*tree[now].Tar;
		tree[now<<1|1].sum=(tree[now<<1|1].r-tree[now<<1|1].l+1)*tree[now].Tar;
		if(tree[now].Tar<0)	tree[now<<1].lsum=tree[now<<1].num=tree[now<<1].rsum=tree[now].Tar;
		else	tree[now<<1].lsum=tree[now<<1].num=tree[now<<1].rsum=tree[now<<1].sum;
		if(tree[now].Tar<0)	tree[now<<1|1].lsum=tree[now<<1|1].num=tree[now<<1|1].rsum=tree[now].Tar;
		else	tree[now<<1|1].lsum=tree[now<<1|1].num=tree[now<<1|1].rsum=tree[now<<1|1].sum;
		tree[now].Tar=-1e5;
	}
}
node merge(node x,node y)
{
    node res;
    res.sum=x.sum+y.sum,res.num=max(x.rsum+y.lsum,max(x.num,y.num));
    res.lsum=max(x.lsum,x.sum+y.lsum),res.rsum=max(y.rsum,y.sum+x.rsum);
    return res;
}
void change_tree(int now,int l,int r,int v)
{
	if(l<=tree[now].l&&tree[now].r<=r)
	{
		tree[now].sum=(tree[now].r-tree[now].l+1)*v;
		if(v<0)	tree[now].lsum=tree[now].num=tree[now].rsum=v;
		else	tree[now].lsum=tree[now].num=tree[now].rsum=tree[now].sum;
		tree[now].Tar=v;
		return;
	}
	fixed_tree(now);
	int mid=(tree[now].l+tree[now].r)/2;
	if(l<=mid)	change_tree(now<<1,l,r,v);
	if(r>mid)	change_tree(now<<1|1,l,r,v);
	pushup(now);
}
node query(int now,int l,int r)
{
	node f1,f2;
	if(l<=tree[now].l&&tree[now].r<=r)	return tree[now];
	fixed_tree(now);
	int mid=(tree[now].l+tree[now].r)/2;
	if(l<=mid)	f1=query(now<<1,l,r);
	if(r>mid)	f2=query(now<<1|1,l,r);
	return merge(f1,f2);
}
void changeway(int l,int r,int v)
{
	while(top[l]!=top[r])
	{
		if(depth[top[l]]<depth[top[r]])	swap(l,r);
		change_tree(1,seg[top[l]],seg[l],v);
		l=fa[top[l]];
	}
	if(depth[l]>depth[r])	swap(l,r);
	change_tree(1,seg[l],seg[r],v);
}
node queryway(int l,int r)
{
	node L,R;
	while(top[l]!=top[r])
	{
		if(depth[top[l]]<depth[top[r]])
		{
			R=merge(R,query(1,seg[top[r]],seg[r]));
			r=fa[top[r]];
		}
		else
		{
			L=merge(L,query(1,seg[top[l]],seg[l]));
			l=fa[top[l]];
		}
	}
	if(depth[l]>depth[r])	L=merge(L,query(1,seg[r],seg[l]));
	else	R=merge(R,query(1,seg[l],seg[r]));
	swap(L.lsum,L.rsum);
	return merge(L,R);
}
void read(int &x)
{
	x=0;
	short flag=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-')	flag=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	x*=flag;
}
int main()
{
	read(n);
	for(int i=1;i<=n;i++)	read(a[i]);
	for(int i=1;i<n;i++)
	{
		int x,y;
		read(x),read(y);
		add(x,y),add(y,x);
	}
	dfs1(1,0),dfs2(1,1);
	build_tree(1,1,n);
	read(m);
	while(m--)
	{
		int opt,x,y,z;
		read(opt),read(x),read(y);
		if(opt==1)	cout<<max(queryway(x,y).num,0)<<endl;
		else	read(z),changeway(x,y,z);
	}
	return 0;
}
2023/1/29 17:42
加载中...