题解 法阵

传送门

发现一个区间内前 \(\log\) 大的数不可能对答案没贡献
于是一个乱搞是线段树取出前 \(\log\) 大的数,单调栈 \(O(n^2)\) 在这 \(\log\) 个中求答案
复杂度 \(O(n\log^2 n)\),可以过 zhengrui 的 200 组数据
但是很好卡,考虑最大的数特别大但是能跟它配对的数很小以至于都不在前 \(\log\) 大里

题目来源:「JOI Open 2019」三级跳
正解先咕着

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 500010
#define fir first
#define sec second
#define pb push_back
#define ll long long
// #define int long long

char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n, m;
ll a[N];

namespace force{
	ll query(int l, int r) {
		ll ans=0;
		for (int y=l+1; y<r; ++y)
			for (int x=l; x<y; ++x)
				for (int z=y+(y-x); z<=r; ++z)
					ans=max(ans, a[x]+a[y]+a[z]);
		return ans;
	}
	void solve() {
		for (int i=1,l,r; i<=m; ++i) {
			l=read(); r=read();
			printf("%lld\n", query(l, r));
		}
	}
}

namespace task1{
	ll ans[N], bit[5010];
	int mx[5010][5010];
	vector<pair<int, int>> que[5010];
	inline void upd(int i, ll dat) {for (; i; i-=i&-i) bit[i]=max(bit[i], dat);}
	inline ll query(int i) {ll ans=0; for (; i<=n; i+=i&-i) ans=max(ans, bit[i]); return ans;}
	void solve() {
		for (int i=1,l,r; i<=m; ++i) {
			l=read(); r=read();
			que[r].pb({l, i});
		}
		for (int i=1; i<=n; ++i)
			for (int j=i; j<=n; ++j)
				mx[i][j]=max(mx[i][j-1], (int)a[j]);
		for (int r=3; r<=n; ++r) {
			for (int l=r-2; l; --l)
				upd(l, a[l]+a[r]+mx[l+1][(l+r)/2]);
			for (auto it:que[r]) ans[it.sec]=query(it.fir);
		}
		for (int i=1; i<=m; ++i) printf("%lld\n", ans[i]);
	}
}

namespace task2{
	ll ans;
	int pos[N], sta[N], top;
	void solve() {
		for (int i=1; i<=n; ++i) pos[i]=i;
		sort(pos+1, pos+n+1, [](int i, int j){return a[i]>a[j];});
		for (int i=1; i<=200; ++i) sta[++top]=pos[i];
		for (int i=1; i<=n; ++i) cout<<a[pos[i]]<<' '; cout<<endl;
		sort(sta+1, sta+top+1);
		for (int x=1; x<=top; ++x)
			for (int y=x+1; y<=top; ++y)
				for (int z=y+1; z<=top; ++z)
					if (sta[y]-sta[x]<=sta[z]-sta[y])
						ans=max(ans, a[sta[x]]+a[sta[y]]+a[sta[z]]);
		cout<<ans<<endl;
	}
}

namespace task3{
	int sta[50], q[50], top, ql, qr;
	int tl[N<<2], tr[N<<2];
	struct buc{
		int dat[18], siz;
		buc():siz(0) {}
		inline int& operator [] (int t) {return dat[t];}
		// inline ll qmax() {
		// 	ll ans=0;
		// 	sort(dat+1, dat+siz+1);
		// 	cout<<"dat: "; for (int i=1; i<=siz; ++i) cout<<dat[i]<<' '; cout<<endl;
		// 	for (int x=1; x<=siz; ++x)
		// 		for (int y=x+1; y<=siz; ++y)
		// 			for (int z=y+1; z<=siz; ++z)
		// 				if (dat[y]-dat[x]<=dat[z]-dat[y])
		// 					ans=max(ans, a[dat[x]]+a[dat[y]]+a[dat[z]]), cout<<dat[x]<<' '<<dat[y]<<' '<<dat[z]<<endl;
		// 	return ans;
		// }
		inline ll qmax() {
			ll ans=0; top=0; ql=1; qr=0;
			sort(dat+1, dat+siz+1);
			for (int i=1; i<=siz; ++i) {
				while (ql<=qr && a[q[qr]]<=a[dat[i]]) --qr;
				q[++qr]=dat[i];
			}
			// for (int i=ql; i<=qr; ++i) cout<<q[i]<<' '; cout<<endl;
			for (int y=1; y<=siz; ++y) {
				// cout<<"y: "<<dat[y]<<endl;
				if (q[ql]==dat[y]) ++ql;
				for (int x=top,z=ql; x; --x) {
					while (z<=qr && dat[y]-sta[x]>q[z]-dat[y]) ++z;
					// if (z<=qr) cout<<"xz: "<<sta[x]<<' '<<q[z]<<endl;
					if (z<=qr) ans=max(ans, a[sta[x]]+a[dat[y]]+a[q[z]]);
				}
				while (top && a[sta[top]]<=a[dat[y]]) --top;
				sta[++top]=dat[y];
			}
			return ans;
		}
	}dat[N<<2];
	inline buc operator + (buc x, buc y) {
		buc ans;
		int p1=1, p2=1, tot=min(x.siz+y.siz, 17);
		for (int i=1; i<=tot; ++i) {
			if (p1>x.siz) ans[i]=y[p2++];
			else if (p2>y.siz) ans[i]=x[p1++];
			else {
				if (a[x[p1]]>=a[y[p2]]) ans[i]=x[p1++];
				else ans[i]=y[p2++];
			}
		}
		ans.siz=tot;
		return ans;
	}
	#define tl(p) tl[p]
	#define tr(p) tr[p]
	#define siz(p) siz[p]
	#define dat(p) dat[p]
	// inline void pushup(int p) {dat(p)=dat(p<<1)+dat(p<<1|1);}
	void build(int p, int l, int r) {
		tl(p)=l; tr(p)=r;
		if (l==r) {dat(p)[1]=l; dat(p).siz=1; return ;}
		int mid=(l+r)>>1;
		build(p<<1, l, mid);
		build(p<<1|1, mid+1, r);
		dat(p)=dat(p<<1)+dat(p<<1|1);
	}
	buc query(int p, int l, int r) {
		if (l<=tl(p)&&r>=tr(p)) return dat(p);
		int mid=(tl(p)+tr(p))>>1;
		if (l<=mid&&r>mid) return query(p<<1, l, r)+query(p<<1|1, l, r);
		else if (l<=mid) return query(p<<1, l, r);
		else return query(p<<1|1, l, r);
	}
	void solve() {
		build(1, 1, n);
		for (int i=1,l,r; i<=m; ++i) {
			l=read(); r=read();
			buc t=query(1, l, r);
			for (int i=1; i<=t.siz; ++i) cout<<t[i]<<' '; cout<<endl;
			printf("%lld\n", query(1, l, r).qmax());
		}
	}
}

signed main()
{
	freopen("fz.in", "r", stdin);
	freopen("fz.out", "w", stdout);

	n=read();
	for (int i=1; i<=n; ++i) a[i]=read();
	m=read();
	// force::solve();
	// task2::solve();
	// task3::solve();
	task::solve();

	return 0;
}
posted @ 2022-03-14 21:48  Administrator-09  阅读(1)  评论(0编辑  收藏  举报