P1792 [国家集训队] 种树

题意:给一个长度为n的环形数组,你要选m个数,满足没有任意两个数的位置相邻,求总和最大。

一开始没仔细看数据范围写了个dp暴力,想着枚举第1个点选还是不选两次dp取最大值。(属于痴心妄想)
后面自己也是看的题解。我们先贪心选最大的,那么它两边就不可以选了,但有可能选两边比选这个更好,那么我们就选两边,这样怎么处理?我们先选了第i个,加上了ai,那么如果我们不选这个而选旁边两个,是不是要加上ai1ai+1,然后要减掉ai。那么我们用一个新点来替代当前点,它的值为ai1 + ai+1 - ai
因为不能相邻,所以m最多n个。
用优先队列和链表模拟即可。

点击查看代码
void solve() {
	int n, m;
	std::cin >> n >> m;
	if (m > n / 2) {
		std::cout << "Error!\n";
		return;
	}

	std::priority_queue<std::pair<int, int> > heap;
	std::vector<int> l(n), r(n), val(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> val[i];
		l[i] = i - 1;
		r[i] = i + 1;	
		heap.push({val[i], i});
	}

	l[0] = n - 1; r[n - 1] = 0;

	auto del = [&](int p) -> void {
		l[r[p]] = l[p];
		r[l[p]] = r[p];
	};

	int ans = 0;
	std::vector<int> vis(n);
	while (m -- ) {
		while (vis[heap.top().second]) {
			heap.pop();
		}

		auto [v, id] = heap.top(); heap.pop();
		vis[l[id]] = vis[r[id]] = 1;
		ans += v;
		val[id] = val[l[id]] + val[r[id]] - v;
		heap.push({val[id], id});
		del(l[id]); del(r[id]);
	}

	std::cout << ans << "\n";
}
posted @   maburb  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示