题解 Skip

发布时间:2022-07-04 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了题解 Skip脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

传送门

CDQ分治优化DP的板子题

发现式子可以整理成 (dp[i]=max{dp[j]+binom{i-j}{2}}+a[i] (i>j, a[i]>a[j])) 的形式 于是用CDQ处理掉后面的两个限制条件,剩下的用斜率优化处理 注意CDQ套斜率优化的时候不能在一开始就把所有决策点都扔进单调队列里 需要等到一个决策点满足限制条件了再扔

Code:
#include <bITs/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define reg register int
#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;
ll a[N];

namespace force{
	ll dp[N];
	inline ll sum(ll k) {return k*(k+1)/2;}
	void solve() {
		memset(dp, 128, sizeof(dp));
		a[0]=-iNF; a[n+1]=INF; dp[0]=0;
		for (int i=1; i<=n; ++i) {
			for (int j=0; j<i; ++j) if (a[j]<=a[i]) {
				dp[i]=max(dp[i], dp[j]-sum(i-j-1));
			}
			dp[i]+=a[i];
		}
		for (int i=0; i<=n; ++i) dp[n+1]=max(dp[n+1], dp[i]-sum(n-i));
		PRintf("%lldn", dp[n+1]);
		exit(0);
	}
}

namespace task1{
	ll dp[N], l=1, r=0;
	// struct que{double val; int pos; inline void build(double v, int p) {val=v; pos=p;}}q[N];
	int q[N];
	inline ll sum(ll k) {return k*(k+1)/2;}
	inline double calc(ll j, ll k) {return ((2.0*dp[k]-k*k+k)-(2.0*dp[j]-j*j+j))/(1.0*j-k);}
	void solve() {
		memset(dp, 128, sizeof(dp));
		a[0]=-INF; a[n+1]=INF; dp[0]=0;
		q[++r]=0;
		for (int i=1; i<=n; ++i) {
			// while (l<r && a[q[l]]>=a[q[l+1]] && calc(q[l], q[l+1])>=double(2*i)) ++l;
			for (int j=l; j<=r; ++j) if (a[q[j]]<=a[i]) {
				dp[i]=max(dp[i], dp[q[j]]-sum(i-q[j]-1));
			}
			dp[i]+=a[i];
			while (l<r && a[q[r-1]]>=a[q[r]] && calc(q[r-1], q[r])<double(2*i)) {/*cout<<calc(q[r-1], q[r])<<endl;*/ --r;}
			q[++r]=i;
		}
		// cout<<"q: "; for (int i=l; i<=r; ++i) cout<<q[i]<<' '; cout<<endl;
		for (int i=l; i<=r; ++i) dp[n+1]=max(dp[n+1], dp[q[i]]-sum(n-q[i]));
		printf("%lldn", dp[n+1]);
		exit(0);
	}
}

namespace task{
	ll dp[N];
	int q[N], p[N];
	inline double calc(ll j, ll k) {return ((2.0*dp[k]-k*k-k)-(2.0*dp[j]-j*j-j))/(1.0*j-k);}
	inline bool cmp1(int i, int j) {return a[i]<a[j];}
	inline ll sum(ll k) {return k*(k+1)/2;}
	void cdq(int l, int r) {
		// cout<<"cdq: "<<l<<' '<<r<<endl;
		if (l==r) {dp[p[l]]+=a[p[l]]; return ;}
		int mid=(l+r)>>1, ql=1, qr=0;
		cdq(l, mid);
		sort(p+l, p+mid+1); sort(p+mid+1, p+r+1);
		// cout<<"sort: "<<l<<' '<<r<<endl;
		// cout<<"p: "; for (int i=l; i<=r; ++i) cout<<p[i]<<' '; cout<<endl;
		// cout<<"a: "; for (int i=l; i<=r; ++i) cout<<a[p[i]]<<' '; cout<<endl;
		// cout<<"q: "; for (int i=ql; i<=qr; ++i) cout<<q[i]<<' '; cout<<endl;
		for (int i=mid+1,pos1=l; i<=r; ++i) {
			// cout<<"calc: "<<p[i]<<' '<<q[ql]<<' '<<q[ql+1]<<' '<<calc(q[ql], q[ql+1])<<' '<<2*p[i]<<endl;
			while (pos1<=mid && p[pos1]<p[i]) {
				while (ql<qr && calc(q[qr-1], q[qr])>calc(q[qr], p[pos1])) --qr;
				q[++qr]=p[pos1];
				++pos1;
			}
			while (ql<qr && p[i]>q[ql+1] && calc(q[ql], q[ql+1])<2*p[i]) {
				// cout<<"a: "<<a[p[i]]<<' '<<a[q[ql+1]]<<endl;
				// cout<<"k: "<<q[ql]<<' '<<q[ql+1]<<' '<<calc(q[ql], q[ql+1])<<' '<<2*p[i]<<endl;
				++ql;
			}
			// cout<<"tran: "<<p[i]<<' '<<q[ql]<<endl;
			if (p[i]>q[ql]) {
				dp[p[i]]=max(dp[p[i]], dp[q[ql]]-sum(p[i]-q[ql]-1));
				// cout<<"tran: "<<p[i]<<' '<<q[ql]<<' '<<dp[q[ql]]-sum(p[i]-q[ql]-1)<<' '<<dp[q[ql]]<<endl;
			}
		}
		sort(p+l, p+r+1, cmp1);
		cdq(mid+1, r);
	}
	void solve() {
		memset(dp, 128, sizeof(dp));
		a[0]=-INF; a[n+1]=INF; dp[0]=INF;
		for (int i=0; i<=n; ++i) p[i]=i;
		sort(p, p+n+1, cmp1);
		cdq(0, n);
		// cout<<"dp: "; for (int i=0; i<=n; ++i) cout<<dp[i]<<' '; cout<<endl;
		for (int i=0; i<=n; ++i) dp[n+1]=max(dp[n+1], dp[i]-sum(n-i));
		printf("%lldn", dp[n+1]);
		exit(0);
	}
}

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

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

	return 0;
}

脚本宝典总结

以上是脚本宝典为你收集整理的题解 Skip全部内容,希望文章能够帮你解决题解 Skip所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。