• 「题解」BZOJ 2151.种树


    题目

    #2151. 种树

    简化题意

    (n) 围成一个环,环上每个点有一个贡献,你要从环上选 (m) 个点(不能相邻)使得选出的点的贡献值的和最大。

    思路

    贪心 + 链表 + 优先队列。

    把贡献都加到大根堆里。

    每次取出最大的贡献 (x),往队里加入 (y + z - x)(y,z) 是在原序列中 (x) 两边的贡献)。

    不知道为啥对,看到还有用 ( ext{WQS二分}) 过了的。

    Code

    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #define MAXN 200001
    
    int n, m, a[MAXN << 1], lt[MAXN << 1], nt[MAXN << 1];
    bool used[MAXN << 1];
    struct Node {
    	int w, id;
    	friend bool operator < (Node n1, Node n2) {
    		return n1.w < n2.w;
    	}
    };
    std::priority_queue<Node> q;
    
    int main() {
    	//freopen("1.in", "r", stdin);
    	scanf("%d %d", &n, &m);
    	if (m > n / 2) {
    		puts("Error!");
    		return 0;
    	}
    	for (int i = 1; i <= n; ++i) {
    		scanf("%d", &a[i]);
    		Node x;
    		x.w = a[i], x.id = i;
    		q.push(x);
    	}
    	for (int i = 1; i <= n; ++i) {
    		if (i == 1) lt[i] = n, nt[i] = 2;
    		else if (i == n) lt[i] = n - 1, nt[i] = 1;
    		else lt[i] = i - 1, nt[i] = i + 1;
    	}
    	int ans = 0;
    	while (!q.empty() && m) {
    		while (used[q.top().id]) q.pop();
    		Node now = q.top(); q.pop();
    		ans += now.w, --m;
    		used[lt[now.id]] = used[nt[now.id]] = true;
    		a[++n] = a[lt[now.id]] + a[nt[now.id]] - now.w;
    		nt[lt[lt[now.id]]] = n, lt[nt[nt[now.id]]] = n;
    		lt[n] = lt[lt[now.id]], nt[n] = nt[nt[now.id]];
    		Node x;
    		x.w = a[n], x.id = n;
    		q.push(x);
    	}
    	std::cout << ans << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    eclipse的web项目热部署
    JAVA字符串转日期或日期转字符串
    右下角弹出框
    div拖拽
    js的富文本框与日期插件
    slected多选框的转移
    判断当前日期是否是当月数据
    java常见面试题(二)
    静态代理和动态代理
    java常见面试题(一)
  • 原文地址:https://www.cnblogs.com/poi-bolg-poi/p/13585432.html
Copyright © 2020-2023  润新知