线段树-山海经 题解
《最痛苦的一集》
从开始的找维护变量 到依据i比较 依据y比较 最后发现问题出在没初始化(
如果不将答案赋值为极小值 那么它最小值就是0
因此 wa了无数遍
下面是思路
首先 要维护的变量有:
\(区间的左右边界 \,l,\,r\)
\(区间的答案 \,ans\)
\(含左端点最大值\,lans\,和含右端点最大值\,rans\)
\(最大值的左右端点 \,lzb,\,yzb\)
\(左答案右端点\,lanzb\,和右答案左端点\,ranzb\)
\(以及区间总和\,sum\)
其次 是update的内容:
- 答案更新
\(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>由 左/右 子的 左/右 答案传递
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;
}