LA3938(线段树)求区间最值范围
本题思想并不复杂,比较麻烦的在于细节部分的处理,对于一些情况是否使用等于对于题目有不同的情况。
首先题目开始要求求出范围内最大值的左端点右端点,因此再遍历时需要对于端点进行更新因此设计上较为复杂。
对于最大值存在两种情况,可能时在M左侧或M右侧或者左右端点在M两侧,因此对于题目的要求我们需要对不同的情况进行不同的讨论。
代码如下
#include <bits/stdc++.h> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) #define mem(x) (memset(x,0,sizeof(x))) typedef vector<int> VI; typedef long long lll; typedef pair<int,int> PII; typedef double db; mt19937 mrand(random_device{}()); const lll mod=1000000007; int rnd(int x) { return mrand() % x;} lll powmod(lll a,lll b) {lll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;} lll gcd(lll a,lll b) { return b?gcd(b,a%b):a;} int n,m; const int maxn=500005; #define mid int M=L+(R-L)/2; #define ls o*2 #define rs o*2+1 struct node { lll num,sum,lsum,rsum; //num为最大值,sum为和,lsum为最大前缀和,rsum为最大后缀和 int l,r,ll,rr; //l,r为最大区间左右端点 ll,rr为最大前后缀端点 }a[maxn<<2]; void update(int o,int L,int R) { mid; //if(o==4) // cout<<a[o].l<<a[o].r<<"%%"; a[o].sum=a[ls].sum+a[rs].sum; a[o].lsum=a[ls].lsum;a[o].rsum=a[rs].rsum; a[o].ll=a[ls].ll;a[o].rr=a[rs].rr; if(a[o].lsum<a[ls].sum+a[rs].lsum) { a[o].lsum=a[ls].sum+a[rs].lsum; a[o].ll=a[rs].ll; } if(a[o].rsum<=a[rs].sum+a[ls].rsum) { a[o].rsum=a[ls].rsum+a[rs].sum; a[o].rr=a[ls].rr; } node tp; if(a[ls].num>=a[rs].num) tp=a[ls]; else tp=a[rs]; a[o].num=tp.num;a[o].l=tp.l;a[o].r=tp.r; lll ans=a[ls].rsum+a[rs].lsum; if(ans>a[o].num||ans==a[o].num&&a[o].l>a[ls].rr|| a[o].num==ans&&a[o].l==a[ls].rr&&a[o].r>a[rs].ll) { a[o].num=ans;a[o].l=a[ls].rr;a[o].r=a[rs].ll; } return ; } void build(int o=1,int L=1,int R=n) { if(L==R) { scanf("%lld",&a[o].sum); // cout<<L<<a[o].sum; a[o].rsum=a[o].lsum=a[o].num=a[o].sum; a[o].r=a[o].rr=a[o].l=a[o].ll=L; // if(o==4) // cout<<a[o].r<<a[o].l; return ; } mid; //cout<<L<<R<<M; build(ls,L,M); build(rs,M+1,R); update(o,L,R); } node query(int l,int r,int o=1,int L=1,int R=n) { if(l==L&&r==R) { // cout<<l<<o<<a[o].l; return a[o]; } mid; if(r<=M) { return query(l,r,ls,L,M); } else if(l>M) { return query(l,r,rs,M+1,R); } else { node t1=query(l,M,ls,L,M); node t2=query(M+1,r,rs,M+1,R); node ret; ret.sum=t1.sum+t2.sum; if(t1.num>=t2.num) { ret=t1; } else ret=t2; lll ans=t1.rsum+t2.lsum; if(ans>ret.num||ans==ret.num&&t1.rr<ret.l ||ans==ret.num&&t1.rr==ret.l&&t2.ll<ret.r) { ret.num=ans;ret.l=t1.rr;ret.r=t2.ll; } ret.lsum=t1.lsum;ret.rsum=t2.rsum; ret.ll=t1.ll;ret.rr=t2.rr; if(ret.lsum<t1.sum+t2.lsum) ret.lsum=t1.sum+t2.lsum,ret.ll=t2.ll; if(ret.rsum<=t2.sum+t1.rsum) ret.rsum=t1.rsum+t2.sum,ret.rr=t1.rr; // cout<<ret.l<<ret.r<<endl; return ret; } } // head int main() { int cas=1; // ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); while(~scanf("%d %d",&n,&m)) { build(); printf("Case %d:\n",cas++); int x,y; rep(i,0,m) { scanf("%d %d",&x,&y); node t=query(x,y); printf("%d %d\n",t.l,t.r); } } }