列表

详情


NC52957. 最大子段和

描述

给一个长为n的序列,有m次查询操作
查询操作形如 l r L R,表示将序列中值在[L,R]内的位置保留不变,其他的位置变成0时,序列中[l,r]区间内的最大子段和,这个子段可以是空的

输入描述

第一行两个数n,m
第二行n个数表示这个序列
之后m行,每行四个数l r L R表示一次查询操作
n,m<=1e5,序列中所有数的绝对值<=1e9

输出描述

输出m行,每行一个数表示答案

示例1

输入:

6 5
-1 1 -4 5 -1 4
1 1 4 5
1 1 4 514
2 3 3 3
1 6 -1 5
2 5 2 5

输出:

0
0
0
9
5

说明:

第四组查询中,值域限制是[-1,5],序列为-1 1 0 5 -1 4,区间[1,6]的最大子段为[2,6],和为9

第五组查询中,值域限制是[2,5],序列为0 0 0 5 0 4,区间[2,5]的最大子段为[4,4](并列),和为5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1369ms, 内存消耗: 17324K, 提交时间: 2020-10-11 21:29:27

#pragma GCC optimize("Ofast")
#include <bits/stdc++.h> 
using namespace std; 
int gi() { 
	int res = 0, w = 1; 
	char ch = getchar(); 
	while (ch != '-' && !isdigit(ch)) ch = getchar(); 
	if (ch == '-') w = -1, ch = getchar(); 
	while (isdigit(ch)) res = res * 10 + ch - '0', ch = getchar(); 
	return res * w; 
} 
typedef long long LL;
const LL INF = 1e18; 
const int MAX_N = 1e5 + 5;
//const int LEN = 300;
int LEN; 
struct data { LL lmx, rmx, mx, sum; } ; 
data operator + (const data &x, const data &y) { 
	data res; 
	res.sum = x.sum + y.sum; 
	res.lmx = max(x.lmx, x.sum + y.lmx); 
	res.rmx = max(y.rmx, y.sum + x.rmx); 
	res.mx = max(x.rmx + y.lmx, max(x.mx, y.mx)); 
	return res; 
} 
int N, Q, a[MAX_N]; 
vector<int> arr; 
vector<vector<data> > vec; 
void Div(int l, int r, vector<int> &arr, vector<vector<data> > &vec) { 
	int n = r - l + 1; 
	arr.resize(n), vec.resize(n); 
	for (int i = 0; i < n; i++) vec[i].resize(n); 
	for (int i = 0; i < n; i++) 
		for (int j = 0; j < n; j++) vec[i][j] = (data){0, 0, -INF, 0}; 
	if (l == r) return (void)(arr[0] = a[l], vec[0][0] = (data){a[l], a[l], a[l], a[l]}); 
	vector<int> al, ar, idl, idr; 
	vector<vector<data> > vl, vr; 
	int mid = (l + r) >> 1; 
	Div(l, mid, al, vl); 
	Div(mid + 1, r, ar, vr); 
	idl.resize(al.size()), idr.resize(ar.size()); 
	int cnt = 0, pl = 0, pr = 0, nl = al.size(), nr = ar.size(); 
	while (pl != nl || pr != nr) { 
		if (pl < nl && (pr == nr || al[pl] < ar[pr])) { 
			idl[pl] = cnt, arr[cnt++] = al[pl++]; 
		} else { 
			idr[pr] = cnt, arr[cnt++] = ar[pr++]; 
		} 
	} 
	for (int i = 0; i < nl; i++) 
		for (int j = i; j < nl; j++) 
			for (int k = idl[i]; k > (i ? idl[i - 1] : -1); k--) 
				for (int l = idl[j]; l < (j < nl - 1 ? idl[j + 1] : n); l++) 
					vec[k][l] = vl[i][j]; 
	for (int i = 0; i < nr; i++) 
		for (int j = i; j < nr; j++) 
			for (int k = idr[i]; k > (i ? idr[i - 1] : -1); k--) 
				for (int l = idr[j]; l < (j < nr - 1 ? idr[j + 1] : n); l++) 
					vec[k][l] = vec[k][l] + vr[i][j]; 
} 
struct Query { int v, id; } ql[MAX_N], qr[MAX_N]; 
bool operator < (const Query &l, const Query &r) { return l.v < r.v; } 
int M, lq[MAX_N], rq[MAX_N], L[MAX_N], R[MAX_N];
data ans[MAX_N]; 
void solve(int l, int r) { 
	Div(l, r, arr, vec); 
	int n = r - l + 1; 
	static int pl[MAX_N], pr[MAX_N]; 
	for (int i = 1, p = 0; i <= Q; i++) { 
		while (p < n && arr[p] < ql[i].v) ++p; 
		pl[ql[i].id] = p; 
	} 
	for (int i = 1, p = 0; i <= Q; i++) { 
		while (p < n && arr[p] < qr[i].v) ++p; 
		pr[qr[i].id] = p; 
	} 
	for (int i = 1; i <= Q; i++) { 
		if (lq[i] <= l && r <= rq[i]) { 
			int x = pl[i], y = pr[i] - 1; 
			if (x <= y) ans[i] = ans[i] + vec[x][y]; 
		} else { 
			for (int j = max(lq[i], l); j <= min(rq[i], r); j++) 
				if (L[i] <= a[j] && a[j] <= R[i]) ans[i] = ans[i] + (data){a[j], a[j], a[j], a[j]}; 
		} 
	} 
} 
int main () { 
#ifndef ONLINE_JUDGE 
    freopen("cpp.in", "r", stdin); 
#endif 
	N = gi(), Q = gi();
	LEN = sqrt(1.0 * N); 
	for (int i = 1; i <= N; i++) a[i] = gi(); 
	for (int i = 1; i <= Q; i++) { 
		lq[i] = gi(), rq[i] = gi(), L[i] = gi(), R[i] = gi(); 
		ql[i] = (Query){L[i], i}, qr[i] = (Query){R[i] + 1, i}; 
	} 
	sort(&ql[1], &ql[Q + 1]); 
	sort(&qr[1], &qr[Q + 1]); 
	for (int i = 1; i <= N; i += LEN) solve(i, min(N, i + LEN - 1)); 
	for (int i = 1; i <= Q; i++) printf("%lld\n", ans[i].mx); 
    return 0; 
} 

C++(g++ 7.5.0) 解法, 执行用时: 1586ms, 内存消耗: 56848K, 提交时间: 2022-09-23 21:39:59

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read() {
	int f=1, r=0; char c=getchar();
	while (!isdigit(c)) f^=c=='-', c=getchar();
	while (isdigit(c)) r=r*10+(c&15), c=getchar();
	return f?r:-r;
}
template<class T> inline void ckmin(T &x, T y) {if (y<x) x=y;}
template<class T> inline void ckmax(T &x, T y) {if (x<y) x=y;}
const int N=1e5+7, M=277;
struct node {
	ll l, r, s, v;
	node(ll _v=0) {s=_v, v=l=r=max(_v, 0ll);}
	node(ll _l, ll _r, ll _s, ll _v) :l(_l), r(_r), s(_s), v(_v) {}
	friend node operator +(const node &a, const node &b) {
		return node(max(a.l, a.s+b.l), max(a.r+b.s, b.r), a.s+b.s, max({a.v, b.v, a.r+b.l}));
	}
	node& operator +=(const node &a) {return *this=*this+a;}
};
struct Query {int l, r, L, R;} q[N];
int n, Q, tot, blk, a[N], bel[N], L[1007], R[1007];
int id1[N], id2[N];
node ans[N];
int lv[10][M], v[10][M];
node lval[10][M][M], val[10][M][M];
void solve(int l, int r, int d) {
	if (l==r) {
		v[d][0]=l, val[d][0][0]=node(a[l]);
		return;
	}
	int mid=(l+r)>>1, lsz=mid-l+1, rsz=r-mid, sz=r-l+1, i=0, j=0, k=0;
	solve(l, mid, d+1);
	for (i=0; i<lsz; i++) {
		lv[d][i]=v[d+1][i];
		for (j=i; j<lsz; j++) lval[d][i][j]=val[d+1][i][j];
	}
	solve(mid+1, r, d+1), i=0, j=0;
	while (i<lsz || j<rsz) {
		if (j==rsz || (i<lsz && a[lv[d][i]]<=a[v[d+1][j]]))
			v[d][k++]=lv[d][i++];
		else v[d][k++]=v[d+1][j++];
	}
	for (k=0, i=0, j=0; k<sz; k++) {
		int I=i-1, J=j-1;
		for (int o=k; o<sz; o++) {
			v[d][o]<=mid?I++:J++; val[d][k][o]=node();
			if (i<=I) val[d][k][o]=lval[d][i][I];
			if (j<=J) val[d][k][o]+=val[d+1][j][J];
		}
		v[d][k]<=mid?i++:j++;
	}
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("1.in", "r", stdin);
	freopen("1.out", "w", stdout);
#endif
	n=read(), Q=read(), blk=max(1., sqrt(n/1.35));
	for (int i=1; i<=n; i++) a[i]=read();
	for (int i=1; i<=n; i++) bel[i]=(i-1)/blk+1;
	tot=bel[n];
	for (int i=1; i<=tot; i++) L[i]=(i-1)*blk+1, R[i]=min(n, i*blk);
	for (int i=1; i<=Q; i++) q[i].l=read(), q[i].r=read(), q[i].L=read(), q[i].R=read(), id1[i]=id2[i]=i;
	sort (id1+1, id1+Q+1, [&](const int &x, const int &y) {return q[x].L<q[y].L;});
	sort (id2+1, id2+Q+1, [&](const int &x, const int &y) {return q[x].R<q[y].R;});
	for (int i=2; i<tot; i++) {
		int l=L[i], r=R[i];
		solve(l, r, 0);
		static int L[N], R[N];
		int sz=r-l+1, p=0;
		for (int j=1; j<=Q; j++) {
			int x=id1[j];
			if (bel[q[x].l]<i && i<bel[q[x].r]) {
				while (p<sz && a[v[0][p]]<q[x].L) p++;
				L[x]=p;
			} else L[x]=sz;
		}
		p=0;
		for (int j=1; j<=Q; j++) {
			int x=id2[j];
			if (bel[q[x].l]<i && i<bel[q[x].r]) {
				while (p<sz && a[v[0][p]]<=q[x].R) p++;
				R[x]=p-1;
			}
		}
		for (int j=1; j<=Q; j++)
			if (L[j]<=R[j])
				ans[j]+=val[0][L[j]][R[j]];
	}
	for (int i=1; i<=Q; i++) {
		int l=q[i].l, r=q[i].r, vl=q[i].L, vr=q[i].R;
		if (bel[l]==bel[r])	{
			for (int j=l; j<=r; j++) if (vl<=a[j] && a[j]<=vr) ans[i]+=node(a[j]);
		} else {
			for (int j=L[bel[r]]; j<=r; j++) if (vl<=a[j] && a[j]<=vr) ans[i]+=node(a[j]);
			for (int j=R[bel[l]]; j>=l; j--) if (vl<=a[j] && a[j]<=vr) ans[i]=node(a[j])+ans[i];
		}
	}
	for (int i=1; i<=Q; i++) printf("%lld\n", ans[i].v);
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 1617ms, 内存消耗: 12132K, 提交时间: 2019-09-22 08:48:43

#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
#define fo(i,a,b)for(int i=a,_e=b;i<=_e;++i)
#define fd(i,a,b)for(int i=b,_e=a;i>=_e;--i)
#define ll long long
#define max(a,b)(a>b?a:b)
#define pb push_back
using namespace std;
const int N=1e5+5,B=200;
int n,m,a[N],le[N],ri[N],Q;
ll ans[N],pre[N];
struct nod{int a,i;}s[N],s2[N],c[N];
bool is[N];
void R(int &n){
	char c;int fh=1;for(n=0;(c=getchar())<'0'||c>'9';)if(c=='-')fh=-1;
	for(;c<='9'&&c>='0';c=getchar())n=n*10+c-48;n*=fh;
}
struct qu{
	int l,r,x,y;
	void Re(){R(x);R(y);R(l);R(r);}
}b[N];
struct tr{ll tl,tr,su,mx;}t[(B+5)*4],aa[N],q[B+5][B+5];
inline void plu(tr &z,const tr x,const tr y){
	z.mx=max(x.mx,y.mx);
	z.mx=max(z.mx,x.tr+y.tl);
	z.tl=max(x.tl,x.su+y.tl);
	z.tr=max(y.tr,y.su+x.tr);
	z.su=x.su+y.su;
}
inline void plus2(ll &ans,ll &pre,const tr x){
	ans=max(ans,x.mx);
	ans=max(ans,pre+x.tl);
	pre=max(pre+x.su,x.tr);
}
bool cmp(nod x,nod y){return x.a<y.a;}
inline void ch(int x,int l){
	t[Q+x-l]=(is[x]^=1)?aa[x]:(tr){0,0,0,0};
	for(x+=Q-l;x>>=1;)plu(t[x],t[x*2],t[x*2+1]);
}
void solve(int l,int r){
	fo(i,l,r)c[i-l]=(nod){a[i],i};
	int sz=r-l+1,p=0;
	sort(c,c+sz,cmp);
	fo(i,1,m){
		for(;p<sz&&c[p].a<s[i].a;)++p;
		le[s[i].i]=p;
	}
	p=0;
	fo(i,1,m){
		for(;p<sz&&c[p].a<=s2[i].a;)++p;
		ri[s2[i].i]=p-1;
	}
	fo(i,1,Q*2-1)t[i]=(tr){0,0,0,0};
	fo(i,0,sz-1)if(i&1){
		ch(c[i-1].i,l);
		fd(j,i,sz-1){
			q[i][j]=t[1];
			ch(c[j].i,l);
		}
	}else{
		fo(j,i,sz-1){
			ch(c[j].i,l);
			q[i][j]=t[1];
		}
	}
	fo(i,1,m)if(l<=b[i].y&&b[i].x<=r){
		if(b[i].x<=l&&r<=b[i].y){
			if(le[i]<=ri[i])plus2(ans[i],pre[i],q[le[i]][ri[i]]);
		}else
			fo(j,l,r)if(b[i].x<=j&&j<=b[i].y&&b[i].l<=a[j]&&a[j]<=b[i].r)
				plus2(ans[i],pre[i],aa[j]);
	}
}
int main(){
	R(n);R(m);
	fo(i,1,n){
		R(a[i]);int s=max(0,a[i]);
		aa[i]=(tr){s,s,a[i],s};
	}
	fo(i,1,m)b[i].Re(),s[i]=(nod){b[i].l,i},s2[i]=(nod){b[i].r,i};
	sort(s+1,s+m+1,cmp);
	sort(s2+1,s2+m+1,cmp);
	for(Q=1;Q<B;Q<<=1);
	fo(i,1,n/B+(n%B!=0))
		solve((i-1)*B+1,min(n,i*B));
	fo(i,1,m)printf("%lld\n",ans[i]);
}

上一题