A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。
标签:
A城市有一个巨大的圆形广场,为了绿化环境和净化空气,市政府决定沿圆形广场外圈种一圈树。园林部门得到指令后,初步规划出n个种树的位置,顺时针编号1到n。并且每个位置都有一个美观度Ai,如果在这里种树就可以得到这Ai的美观度。但由于A城市土壤肥力欠佳,两棵树决不能种在相邻的位置(i号位置和i+1号位置叫相邻位置。值得注意的是1号和n号也算相邻位置!)。最终市政府给园林部门提供了m棵树苗并要求全部种上,请你帮忙设计种树方案使得美观度总和最大。如果无法将m棵树苗全部种上,给出无解信息。
输入的第一行包含两个正整数n、m。第二行n个整数Ai。
输出一个整数,表示最佳植树方案可以得到的美观度。如果无解输出“Error!”,不包含引号。
堆贪心。
每次选择美观度最大的点x, 将x左边的点L和x右边的点R删去。
但是这样贪心可能无法保证正确性, 需要将操作实现可撤销。
每次选择美观度最大的点x后, 将x左边的点L和x右边的点R删去, 将x再次push进堆, 并使a[x] = a[L] + a[R] - a[x];
具体实现可使用双向链表维护L,R
#include<bits/stdc++.h> using namespace std; const int MAXN = 2e5 + 5; inline void read(int &x) { static int f; static char c; for (f = 1; !isdigit(c = getchar()); ) if (c == ‘-‘) f = -1; for (x = 0; isdigit(c); c = getchar()) x = x * 10 + c - 48; x *= f; } struct data { int v, p; bool operator < (const data &X) const { return v < X.v; } }; priority_queue<data> Q; int ans; int N, M; int a[MAXN]; int pre[MAXN]; int nxt[MAXN]; bool del[MAXN]; void Insert() { while (del[Q.top().p]) Q.pop(); data X = Q.top(); Q.pop(); int P = X.p; ans += a[P]; a[P] = a[pre[P]] + a[nxt[P]] - a[P]; Q.push((data) {a[P], P}); nxt[pre[pre[P]]] = P; pre[nxt[nxt[P]]] = P; del[nxt[P]] = del[pre[P]] = 1; pre[P] = pre[pre[P]]; nxt[P] = nxt[nxt[P]]; } int main() { read(N), read(M); if (N < M * 2) { puts("Error!"); return 0; } for (int i = 1; i <= N; ++ i) { read(a[i]); Q.push((data) {a[i], i}); pre[i] = i - 1; nxt[i] = i + 1; } pre[1] = N; nxt[N] = 1; while (M --) { Insert(); } printf("%d", ans); return 0; }
标签:
原文地址:http://www.cnblogs.com/jszyxw/p/5508472.html