ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 Skip

2021-09-30 08:01:12  阅读:130  来源: 互联网

标签:qr int 题解 long Skip ql dp define


传送门

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("%lld\n", 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("%lld\n", 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("%lld\n", 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;
}

标签:qr,int,题解,long,Skip,ql,dp,define
来源: https://www.cnblogs.com/narration/p/15355144.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有