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

这个其实和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 }
予明日所有失败者 赋万千不灭颂歌

浙公网安备 33010602011771号