ICode9

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

SP6779 GSS7 - Can you answer these queries VII

2022-08-19 15:00:20  阅读:124  来源: 互联网

标签:ctlt twd these SP6779 VII int sum top SIZE


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;
}

标签:ctlt,twd,these,SP6779,VII,int,sum,top,SIZE
来源: https://www.cnblogs.com/hanx16msgr/p/16601992.html

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

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

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

ICode9版权所有