其他分享
首页 > 其他分享> > Codeforces 354D - Transferring Pyramid(DP)

Codeforces 354D - Transferring Pyramid(DP)

作者:互联网

Codeforces 题面传送门 & 洛谷题面传送门

好久没写题解了,写一篇找找感觉吧(

首先发现答案不超过 \(3k\),也就是说,我们选择的三角形的高度是 \(\mathcal O(\sqrt{k})\) 级别的,准确来说,\(\sqrt{6k}\)。故对于 \(y>\sqrt{6k}\) 的点我们肯定会选择花费 \(3\) 的代价使用 1 操作将其搞定。

接下来考虑怎样处理 \(y\le\sqrt{6k}\) 的部分的贡献。考虑从右到左处理,设 \(dp_{i,j}\) 表示目前钦定了 \(i\) 之后的部分的高度,第 \(i\) 列的高度为 \(j\) 的最小代价,那么有转移 \(dp_{i,j}+w(i-1,j)\to dp_{i-1,j+1},dp_{i,j}+w(i-1,k)+\dfrac{k(k+1)}{2}\to dp_{i-1,k}\),其中 \(w(i,j)=3\sum\limits_{x_k=i,y_k>j}1\)

时间复杂度 \(n\sqrt{k}\)。

const int MAXN = 1e5;
const int INF = 0x3f3f3f3f;
int n, k, dp[MAXN + 5];
vector<int> vec[MAXN + 5];
int main() {
	scanf("%d%d", &n, &k);
	for (int i = 1, x, y; i <= k; i++) scanf("%d%d", &x, &y), vec[y].pb(n - x + 1);
	for (int i = n; i; i--) {
		int lim = min(800, n - i + 1);
		for (int pos : vec[i]) {
			for (int j = 0; j <= min(lim, pos - 1); j++) {
				chkmin(dp[pos], dp[j]); dp[j] += 3;
			}
		}
		static int tmp[MAXN + 5]; tmp[0] = dp[0];
		for (int j = 0; j <= lim; j++) {
			tmp[j + 1] = dp[j];
			chkmin(tmp[0], dp[j] + j * (j + 1) / 2 + 2);
		}
		for (int j = 0; j <= lim + 1; j++) dp[j] = tmp[j];
	}
	printf("%d\n", dp[0]);
	return 0;
}

标签:Pyramid,int,Transferring,Codeforces,sqrt,354D,MAXN,6k,dp
来源: https://www.cnblogs.com/ET2006/p/Codeforces-354D.html