线段树-山海经 题解

《最痛苦的一集》

image

从开始的找维护变量 到依据i比较 依据y比较 最后发现问题出在没初始化(
如果不将答案赋值为极小值 那么它最小值就是0
因此 wa了无数遍

下面是思路

首先 要维护的变量有:
\(区间的左右边界 \,l,\,r\)
\(区间的答案 \,ans\)
\(含左端点最大值\,lans\,和含右端点最大值\,rans\)
\(最大值的左右端点 \,lzb,\,yzb\)
\(左答案右端点\,lanzb\,和右答案左端点\,ranzb\)
\(以及区间总和\,sum\)

其次 是update的内容:

  1. 答案更新
    \(ans\)由它的子节点传导而来的路径有三条:
    1>由左子答案传递
    2>由右子答案传递
    3>由左子的右答案和右子的左答案合并而来
    还有需要注意的是一定要尽量选取较小的i与j值 才能符合题意
    表示出来就是(写复杂了
if(rm[id].ans<=rm[id*2].ans)
{
	if(rm[id].ans==rm[id*2].ans)
	{
		if(rm[id].lzb>rm[id*2].lzb)
		{
			rm[id].lzb=rm[id*2].lzb;
			rm[id].rzb=rm[id*2].rzb;
		}
		else if(rm[id].lzb==rm[id*2].lzb&&rm[id].rzb>rm[id*2].rzb)
		{
			rm[id].lzb=rm[id*2].lzb;
			rm[id].rzb=rm[id*2].rzb;
		}
	}
	else
	{
		rm[id].ans=rm[id*2].ans;
		rm[id].lzb=rm[id*2].lzb,rm[id].rzb=rm[id*2].rzb;
	}
}
if(rm[id].ans<=rm[id*2+1].ans)
{
	if(rm[id].ans==rm[id*2+1].ans)
	{
		if(rm[id].lzb>rm[id*2+1].lzb)
		{
			rm[id].lzb=rm[id*2+1].lzb;
			rm[id].rzb=rm[id*2+1].rzb;
		}
		else if(rm[id].lzb==rm[id*2+1].lzb&&rm[id].rzb>rm[id*2+1].rzb)
		{
			rm[id].lzb=rm[id*2+1].lzb;
			rm[id].rzb=rm[id*2+1].rzb;
		}
	}
	else
	{
		rm[id].ans=rm[id*2+1].ans;
		rm[id].lzb=rm[id*2+1].lzb,rm[id].rzb=rm[id*2+1].rzb;
	}
}
if(rm[id].ans<=rm[id*2].rans+rm[id*2+1].lans)
{
	if(rm[id].ans==rm[id*2].rans+rm[id*2+1].lans)
	{
		if(rm[id].lzb>rm[id*2].ranzb)
		{
			rm[id].ans=rm[id*2].rans+rm[id*2+1].lans;
			rm[id].lzb=rm[id*2].ranzb,rm[id].rzb=rm[id*2+1].lanzb;
		}
		else if(rm[id].lzb==rm[id*2].ranzb&&rm[id].rzb>rm[id*2+1].lanzb)
		{
			rm[id].ans=rm[id*2].rans+rm[id*2+1].lans;
			rm[id].lzb=rm[id*2].ranzb,rm[id].rzb=rm[id*2+1].lanzb;
		}
	}
	else
	{
		rm[id].ans=rm[id*2].rans+rm[id*2+1].lans;
		rm[id].lzb=rm[id*2].ranzb,rm[id].rzb=rm[id*2+1].lanzb;
	}
}
  1. 左右答案更新
    这一步较为简单 只有两种情况
    1>由 左/右 子的 左/右 答案传递
    2>由 左/右 的总和加上 右/左 的 左/右 答案迷迷糊糊
    代码如下 有一个小点需单独注意 就是判断时的取等问题
    在取左答案时 要取尽量小的\(j\) 所以取等时更新
    而在取右答案时 要尽量取小\(i\) 所以取等时不更新
    code:
if(rm[id*2+1].rans>rm[id*2+1].sum+rm[id*2].rans)
{
	rm[id].rans=rm[id*2+1].rans;
	rm[id].ranzb=rm[id*2+1].ranzb;
}
else
{
	rm[id].rans=rm[id*2+1].sum+rm[id*2].rans;
	rm[id].ranzb=rm[id*2].ranzb;
}
if(rm[id*2].lans>=rm[id*2].sum+rm[id*2+1].lans)
{
	rm[id].lans=rm[id*2].lans;
	rm[id].lanzb=rm[id*2].lanzb;
}
else
{
	rm[id].lans=rm[id*2].sum+rm[id*2+1].lans;
	rm[id].lanzb=rm[id*2+1].lanzb;
}

剩下的 便是查询了 由于我一开始将update写错了位置 导致以上内容需要写两遍。。

总之 一道很好的线段树 使我的线段旋转 思路找起来不是很费劲 主要是代码。。

code:

OwO
#include <bits/stdc++.h>
#define fo(x,y,z) for(int (x)=(y);(x)<=(z);(x)++)
#define fu(x,y,z) for(int (x)=(y);(x)>=(z);(x)++)
#define foo(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
using namespace std;
typedef long long ll;
inline int qr()
{
	char ch=getchar();int x=0,f=1;
	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
	for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);
	return f*x;
}
#define qr qr()
const int Ratio=0;
const int N=200005;
const int maxx=INT_MAX;
int n,m;
int a[N];
struct stre
{
	int l,r,sum;
	int lans=-maxx,rans=-maxx,ans=-maxx;//zuiyou zuo you
	int lzb,rzb;//zuiyouduandian
	int lanzb,ranzb;//
}rm[N<<2];
void update(int id)
{
	rm[id].sum=rm[id*2].sum+rm[id*2+1].sum;
	if(rm[id].ans<=rm[id*2].ans)
	{
		if(rm[id].ans==rm[id*2].ans)
		{
			if(rm[id].lzb>rm[id*2].lzb)
			{
				rm[id].lzb=rm[id*2].lzb;
				rm[id].rzb=rm[id*2].rzb;
			}
			else if(rm[id].lzb==rm[id*2].lzb&&rm[id].rzb>rm[id*2].rzb)
			{
				rm[id].lzb=rm[id*2].lzb;
				rm[id].rzb=rm[id*2].rzb;
			}
		}
		else
		{
			rm[id].ans=rm[id*2].ans;
			rm[id].lzb=rm[id*2].lzb,rm[id].rzb=rm[id*2].rzb;
		}
	}
	if(rm[id].ans<=rm[id*2+1].ans)
	{
		if(rm[id].ans==rm[id*2+1].ans)
		{
			if(rm[id].lzb>rm[id*2+1].lzb)
			{
				rm[id].lzb=rm[id*2+1].lzb;
				rm[id].rzb=rm[id*2+1].rzb;
			}
			else if(rm[id].lzb==rm[id*2+1].lzb&&rm[id].rzb>rm[id*2+1].rzb)
			{
				rm[id].lzb=rm[id*2+1].lzb;
				rm[id].rzb=rm[id*2+1].rzb;
			}
		}
		else
		{
			rm[id].ans=rm[id*2+1].ans;
			rm[id].lzb=rm[id*2+1].lzb,rm[id].rzb=rm[id*2+1].rzb;
		}
	}
	if(rm[id].ans<=rm[id*2].rans+rm[id*2+1].lans)
	{
		if(rm[id].ans==rm[id*2].rans+rm[id*2+1].lans)
		{
			if(rm[id].lzb>rm[id*2].ranzb)
			{
				rm[id].ans=rm[id*2].rans+rm[id*2+1].lans;
				rm[id].lzb=rm[id*2].ranzb,rm[id].rzb=rm[id*2+1].lanzb;
			}
			else if(rm[id].lzb==rm[id*2].ranzb&&rm[id].rzb>rm[id*2+1].lanzb)
			{
				rm[id].ans=rm[id*2].rans+rm[id*2+1].lans;
				rm[id].lzb=rm[id*2].ranzb,rm[id].rzb=rm[id*2+1].lanzb;
			}
		}
		else
		{
			rm[id].ans=rm[id*2].rans+rm[id*2+1].lans;
			rm[id].lzb=rm[id*2].ranzb,rm[id].rzb=rm[id*2+1].lanzb;
		}
	}
	if(rm[id*2+1].rans>rm[id*2+1].sum+rm[id*2].rans)
	{
		rm[id].rans=rm[id*2+1].rans;
		rm[id].ranzb=rm[id*2+1].ranzb;
	}
	else
	{
		rm[id].rans=rm[id*2+1].sum+rm[id*2].rans;
		rm[id].ranzb=rm[id*2].ranzb;
	}
	if(rm[id*2].lans>=rm[id*2].sum+rm[id*2+1].lans)
	{
		rm[id].lans=rm[id*2].lans;
		rm[id].lanzb=rm[id*2].lanzb;
	}
	else
	{
		rm[id].lans=rm[id*2].sum+rm[id*2+1].lans;
		rm[id].lanzb=rm[id*2+1].lanzb;
	}
}
void build(int id,int l,int r)
{
	rm[id].l=l,rm[id].r=r;
	if(l==r)
	{
		rm[id].sum=rm[id].ans=rm[id].lans=rm[id].rans=a[l];
		rm[id].lanzb=rm[id].ranzb=rm[id].lzb=rm[id].rzb=l;
		return;
	}
	int mid=(l+r)>>1;
	build(id*2,l,mid);
	build(id*2+1,mid+1,r);
	update(id);
}
stre que(int id,int l,int r)
{	
	if(rm[id].l>=l&&rm[id].r<=r)
	{
		return rm[id];
	}
	int mid=(rm[id].l+rm[id].r)>>1;
	if(l>mid)
		return que(id*2+1,l,r);
	else if(r<=mid)
		return que(id*2,l,r);
	else
	{
		stre ans,ll,rr;
		ll=que(id*2,l,r);
		rr=que(id*2+1,l,r);
		ans.l=ll.l,ans.r=rr.r;
		ans.sum=ll.sum+rr.sum;
		
		if(ans.ans<=ll.ans)
		{
			if(ans.ans==ll.ans)
			{
				if(ans.lzb>ll.lzb)
				{
					ans.lzb=ll.lzb;
					ans.rzb=ll.rzb;
				}
				else if(ans.lzb==ll.lzb&&ans.rzb>ll.rzb)
				{
					ans.lzb=ll.lzb;
					ans.rzb=ll.rzb;
				}
			}
			else
			{
				ans.ans=ll.ans;
				ans.lzb=ll.lzb,ans.rzb=ll.rzb;
			}
		}
		if(ans.ans<=rr.ans)
		{
			if(ans.ans==rr.ans)
			{
				if(ans.lzb>rr.lzb)
				{
					ans.lzb=rr.lzb;
					ans.rzb=rr.rzb;
				}
				else if(ans.lzb==rr.lzb&&ans.rzb>rr.rzb)
				{
					ans.lzb=rr.lzb;
					ans.rzb=rr.rzb;
				}
			}
			else
			{
				ans.ans=rr.ans;
				ans.lzb=rr.lzb,ans.rzb=rr.rzb;
			}
		}
		if(ans.ans<=ll.rans+rr.lans)
		{
			if(ans.ans==ll.rans+rr.lans)
			{
				if(ans.lzb>ll.ranzb)
				{
					ans.ans=ll.rans+rr.lans;
					ans.lzb=ll.ranzb,ans.rzb=rr.lanzb;
				}
				else if(ans.lzb==ll.ranzb&&ans.rzb>rr.lanzb)
				{
					ans.ans=ll.rans+rr.lans;
					ans.lzb=ll.ranzb,ans.rzb=rr.lanzb;
				}
			}
			else
			{
				ans.ans=ll.rans+rr.lans;
				ans.lzb=ll.ranzb,ans.rzb=rr.lanzb;
			}
		}
		if(rr.rans>rr.sum+ll.rans)
		{
			ans.rans=rr.rans;
			ans.ranzb=rr.ranzb;
		}
		else
		{
			ans.rans=rr.sum+ll.rans;
			ans.ranzb=ll.ranzb;
		}
		if(ll.lans>=ll.sum+rr.lans)
		{
			ans.lans=ll.lans;
			ans.lanzb=ll.lanzb;
		}
		else
		{
			ans.lans=ll.sum+rr.lans;
			ans.lanzb=rr.lanzb;
		}
		return ans;
	}
}
int main()
{
//	freopen("hill2.in","r",stdin);
	n=qr,m=qr;
	fo(i,1,n)
		a[i]=qr;
	build(1,1,n);
	fo(i,1,m)
	{
		int aa=qr,bb=qr;
		stre aaaaa=que(1,aa,bb);
		printf("%d %d %d\n",aaaaa.lzb,aaaaa.rzb,aaaaa.ans);
	}
	return Ratio;
}
posted @ 2024-02-20 17:15  DrRatio  阅读(55)  评论(3编辑  收藏  举报