山海经 题解

其实是一道咕了很久的题,基础线段树压轴题

 

这个其实和hotel很相似,都是线段树合并,只不过这个题不用下传标记,但要记录路径

多维护几个变量,查询时候直接返回一个结构体,便于操作

区间最大子段和s来源有三个:左子树的s,右子树的s,左子树的从右开始最大和rs与右子树从左开始最大和ls之和

ls来源两个,左子树的ls,左子树区间总和sum与右子树ls之和;rs同理 

还有s的左右端点ll与rr,以及用到的ls右端点lt和rs左端点rt,用来记录路径

if判断时取舍要注意,根据s的情况更新左右端点,由于题目让找最左边的,所以判断是要注意顺序,有一个覆盖答案问题

我用了一个判断条件(最长的内行),看看当前端点是否靠左,如果不够靠左就更新答案

代码不短,但理解了就不难

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 struct tree{
  4     int id,l,r;
  5     int sum,ls,rs,s;
  6     int ll,rr,lt,rt;
  7 }a[500000];
  8 int b[100005];
  9 void build(int id,int l,int r)
 10 {
 11     a[id].l=l;a[id].r=r;
 12     if(l==r)
 13     {
 14         a[id].s=a[id].sum=a[id].ls=a[id].rs=b[l];
 15         a[id].ll=a[id].rr=a[id].rt=a[id].lt=l;
 16         return;
 17     }
 18     int mid=(l+r)/2;
 19     build(id*2,l,mid);build(id*2+1,mid+1,r);
 20     a[id].ls=max(a[id*2].ls,a[id*2].sum+a[id*2+1].ls);
 21     if(a[id].ls==a[id*2].sum+a[id*2+1].ls)a[id].lt=a[id*2+1].lt;
 22     if(a[id].ls==a[id*2].ls)a[id].lt=a[id*2].lt;
 23     a[id].rs=max(a[id*2+1].rs,a[id*2+1].sum+a[id*2].rs);
 24     if(a[id].rs==a[id*2+1].rs)a[id].rt=a[id*2+1].rt;
 25     if(a[id].rs==a[id*2+1].sum+a[id*2].rs)a[id].rt=a[id*2].rt;
 26     a[id].sum=a[id*2].sum+a[id*2+1].sum;
 27     a[id].s=max(max(a[id*2].s,a[id*2+1].s),a[id*2].rs+a[id*2+1].ls);
 28     int sb=0;
 29     if(a[id].s==a[id*2+1].s)
 30     {
 31         a[id].rr=a[id*2+1].rr;a[id].ll=a[id*2+1].ll;
 32         sb=1;
 33     } 
 34     if(a[id].s==a[id*2+1].ls+a[id*2].rs)
 35     {
 36         if((!sb)||a[id].ll>a[id*2].rt||(a[id].ll==a[id*2].rt&&a[id].rr>a[id].lt))
 37         a[id].ll=a[id*2].rt,a[id].rr=a[id*2+1].lt,sb=1;
 38     }
 39     if(a[id].s==a[id*2].s)
 40     {
 41         if((!sb)||a[id].ll>a[id*2].ll||(a[id].ll==a[id*2].ll&&a[id].rr>a[id*2].rr))
 42         a[id].rr=a[id*2].rr,a[id].ll=a[id*2].ll,sb=1;
 43     }
 44 }
 45 inline tree cha(int id,int l,int r)
 46 {
 47     tree p;
 48     if(a[id].l==l&&a[id].r==r)
 49     {
 50         p.l=a[id].l;p.r=a[id].r;p.s=a[id].s;
 51         p.sum=a[id].sum;p.ls=a[id].ls;p.rs=a[id].rs;
 52         p.lt=a[id].lt;p.rt=a[id].rt;
 53         p.ll=a[id].ll;p.rr=a[id].rr;
 54         return p;
 55     }
 56     int mid=(a[id].l+a[id].r)/2;
 57     if(r<=mid)return cha(id*2,l,r);
 58     if(l>mid)return cha(id*2+1,l,r);
 59     tree x=cha(id*2,l,mid),y=cha(id*2+1,mid+1,r);
 60     p.ls=max(x.ls,x.sum+y.ls);
 61     if(p.ls==x.sum+y.ls)p.lt=y.lt;
 62     if(p.ls==x.ls)p.lt=x.lt;
 63     p.rs=max(y.rs,y.sum+x.rs);
 64     if(p.rs==y.rs)p.rt=y.rt;
 65     if(p.rs==y.sum+x.rs)p.rt=x.rt;
 66     p.sum=x.sum+y.sum;
 67     p.s=max(max(x.s,y.s),x.rs+y.ls);
 68     int sb=0;
 69     if(p.s==y.s)
 70     {
 71         p.rr=y.rr;p.ll=y.ll;
 72         sb=1;
 73     } 
 74     if(p.s==y.ls+x.rs)
 75     {
 76         if((!sb)||p.ll>x.rt||(p.ll==x.rt&&p.rr>y.rt))
 77         p.ll=x.rt,p.rr=y.lt,sb=1;
 78     }
 79     if(p.s==x.s)
 80     {
 81         if((!sb)||p.ll>x.ll||(p.ll==x.ll&&p.rr>x.rr))
 82         p.rr=x.rr,p.ll=x.ll,sb=1;
 83     }
 84     return p;
 85 }
 86 int main()
 87 {
 88     int n,m;
 89     cin>>n>>m;
 90     for(int i=1;i<=n;i++)
 91        scanf("%d",&b[i]);
 92     build(1,1,n); 
 93     for(int i=1;i<=m;i++)
 94     {
 95         int l,r;
 96         scanf("%d%d",&l,&r);
 97         tree p=cha(1,l,r);
 98         printf("%d %d %d\n",p.ll,p.rr,p.s);
 99     } 
100     return 0;
101 }
View Code

 

posted @ 2021-05-16 19:00  D'A'T  阅读(79)  评论(0)    收藏  举报