SP6779 GSS7 - Can you answer these queries VII

GSS7 - Can you answer these queries VII

GSS7 (Luogu)

题面翻译

题目描述

给定一棵树,有\(N(N \le 100000)\)个节点,每一个节点都有一个权值\(x_i (|x_i| \le 10000)\)

你需要执行\(Q (Q \le 100000)\)次操作:

  1. 1 a b 查询(a,b)这条链上的最大子段和,可以为空(即输出\(0\)
  2. 2 a b c(a,b)这条链上的所有点权变为c \((|c| <= 10000)\)

输入格式:

第一行一个整数\(N\)

接下来一行有\(N\)个整数表示\(x_i\)

接下来\(N-1\)行,每行两个整数\(u,v\)表示\(u\)\(v\)之间有一条边相连

接下来一行一个整数\(Q\)

之后有\(Q\)行,每行诸如1 a b或者2 a b c

输出格式

对于每一个询问,输出答案

输入样例

5
-3 -2 1 2 3
1 2
2 3
1 4
4 5
3
1 2 5
2 3 4 2
1 2 5

输出样例

5
9

题目描述

Given a tree with N (N <= 100000) nodes. Each node has a interger value x_i (|x_i| <= 10000).

You have to apply Q (Q <= 100000) operations:

1. 1 a b : answer the maximum contiguous sum (maybe empty,will always larger than or equal to 0 ) from the path a->b ( inclusive ).

2. 2 a b c : change all value in the path a->b ( inclusive ) to c. (|c| <= 10000)

输入格式

first line consists one interger N.

next line consists N interger x_i.

next N-1 line , each consists two interger u,v , means that node u and node v are connected

next line consists 1 interger Q.

next Q line : 1 a b or 2 a b c .

输出格式

For each query, output one line the maximum contiguous sum.

样例 #1

样例输入 #1

5
-3 -2 1 2 3
1 2
2 3
1 4
4 5
3
1 2 5
2 3 4 2
1 2 5

样例输出 #1

5
9

Solution

GSS 系列第 \(7\)(别问我为什么前面只做了两道题就来看第 \(7\) 题了)

有区间推平操作不用珂朵莉树水一水真的太可惜了(逃

树上操作并不方便处理,所以用树剖把拆到链上进行解决。修改操作很简单,直接用珂朵莉树自带的assign操作即可。问题是在于如何求解这个链上的最大子段和。

既然都用珂朵莉树了,那么求最大子段和就用最暴力的方法就可以了,即直接将区间提取出来,直接将区间和加入最大子段和内并尝试更新答案;如果此时的子段和已经为负数了,那么就将这个值赋为 \(0\),表示前面的子段全部舍弃(话说这部分应该是 pj 组内容吧,只不过是在珂朵莉树上实现的)。

在树剖过后的重链上跑这种珂朵莉树需要注意链的边界上的问题,因为链与链之间并不是独立的,边界的值是会相互影响,所以需要记下边界的子段和,在进入下一个重链的时候在这个子段和的基础上继续计算。

代码难度的话不算特别大,但是我也调了好一会才写出来,细节还是比较恼火的(才不是忘了调用树剖的两个 dfs 的呢,绝对不是 ~)。

Code

#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof a)
//#define int long long
using namespace std;
template<typename T> void read(T &k)
{
	k=0;T flag=1;char b=getchar();
	while (!isdigit(b)) {flag=(b=='-')?-1:1;b=getchar();}
	while (isdigit(b)) {k=k*10+b-48;b=getchar();}
	k*=flag;
}
template<typename T> void write(T k) {if (k<0) {putchar('-'),write(-k);return;}if (k>9) write(k/10);putchar(k%10+48);}
template<typename T> void writewith(T k,char c) {write(k);putchar(c);}
const int _SIZE=1e5;
int n,q,a[_SIZE+5];
struct EDGE{
	int nxt,to;
}edge[(_SIZE<<1)+5];
int tot,head[_SIZE+5];
void AddEdge(int x,int y)
{
	edge[++tot]=(EDGE){head[x],y};
	head[x]=tot;
}
struct Node{
	int l,r;
	mutable int v;
	Node(){}
	Node(int l,int r=0,int v=0) : l(l),r(r),v(v) {}
	bool operator< (const Node & a) const {return l<a.l;}
};
set<Node> ctlt;
auto split(int pos)
{
	auto it=ctlt.lower_bound(Node(pos));
	if (it!=ctlt.end() && it->l==pos) return it;it--;
	int l=it->l,r=it->r,v=it->v;
	ctlt.erase(it);
	ctlt.insert(Node(l,pos-1,v));
	return ctlt.insert(Node(pos,r,v)).first;
}
void assign(int l,int r,int v)
{
	auto itr=split(r+1),itl=split(l);
	ctlt.erase(itl,itr);
	ctlt.insert(Node(l,r,v));
}
int query(int l,int r,int &basic)
{
	int sum=basic,res=basic;
	auto itr=split(r+1),itl=split(l);
	itl--,itr--;
	for (auto it=itr;it!=itl;it--)
	{
		sum+=it->v*(it->r-it->l+1);
		res=max(res,sum);sum=max(sum,0);
	}
	basic=sum;
	return res;
}
int son[_SIZE+5],id[_SIZE+5],siz[_SIZE+5],cnt;
int top[_SIZE+5],dep[_SIZE+5],fa[_SIZE+5];
void dfs1(int x,int f,int depth)
{
	siz[x]=1,dep[x]=depth,fa[x]=f;
	int maxson=-1;
	for (int i=head[x];i;i=edge[i].nxt)
	{
		int twd=edge[i].to;
		if (twd==f) continue;
		dfs1(twd,x,depth+1);
		siz[x]+=siz[twd];
		if (siz[twd]>maxson) maxson=siz[twd],son[x]=twd;
	}
}
int newx[_SIZE+5];
void dfs2(int x,int topf)
{
	top[x]=topf;
	id[x]=++cnt;
	newx[cnt]=a[x];
	if (!son[x]) return;
	dfs2(son[x],topf);
	for (int i=head[x];i;i=edge[i].nxt)
	{
		int twd=edge[i].to;
		if (twd==fa[x] || twd==son[x]) continue;
		dfs2(twd,twd);
	}
}
void assignRange(int x,int y,int v)
{
	while (top[x]!=top[y])
	{
		if (dep[top[x]]<dep[top[y]]) swap(x,y);
		assign(id[top[x]],id[x],v);
		x=fa[top[x]];
	}
	if (dep[x]>dep[y]) swap(x,y);
	assign(id[x],id[y],v);
}
int queryRange(int x,int y)
{
	int flag1=0,flag2=0,ans=0;
	while (top[x]!=top[y])
	{
		if (dep[top[x]]<dep[top[y]]) swap(x,y),swap(flag1,flag2);
		ans=max(ans,query(id[top[x]],id[x],flag1));
		x=fa[top[x]];
	}
	if (dep[x]>dep[y]) swap(x,y),swap(flag1,flag2);
	swap(flag1,flag2);
	ans=max(ans,query(id[x],id[y],flag1));
	ans=max(ans,flag1+flag2);
	return ans;
}
signed main()
{
	read(n);
	for (int i=1;i<=n;i++) read(a[i]);
	for (int i=1;i<n;i++)
	{
		int u,v;read(u),read(v);
		AddEdge(u,v),AddEdge(v,u);
	}
	dfs1(1,0,1);
	dfs2(1,1);
	for (int i=1;i<=n;i++) ctlt.insert(Node(i,i,newx[i]));
	read(q);
	for (int i=1;i<=q;i++)
	{
		int op,x,y,v;read(op),read(x),read(y);
		if (op==2) read(v),assignRange(x,y,v);
		else writewith(queryRange(x,y),'\n');
	}
	return 0;
}

posted @ 2022-08-19 14:54  Hanx16Msgr  阅读(34)  评论(0编辑  收藏  举报