(堆)P1484 種樹
阿新 • • 發佈:2018-11-28
cyrcyr今天在種樹,他在一條直線上挖了n個坑。這n個坑都可以種樹,但為了保證每一棵樹都有充足的養料,cyrcyr不會在相鄰的兩個坑中種樹。而且由於cyrcyr的樹種不夠,他至多會種k棵樹。假設cyrcyr有某種神能力,能預知自己在某個坑種樹的獲利會是多少(可能為負),請你幫助他計算出他的最大獲利。n<=500000,k<=n/2
6 3
100 1 -1 100 1 -1
200
看到題目第一想法是dp,發現dp陣列開不了這麼大
看題解,大佬真的太強辣
每次如果a[i]是最大值,那麼就不能選a[i - 1]和a[i + 1],則刪掉a[i - 1]和a[i + 1],新添一個點為a[i - 1] + a[i + 1] - a[i]相當於反悔選擇a[i]而選擇a[i - 1]和a[i + 1]將a[i]的影響去掉,不能單選a[i - 1]和a[i + 1]中的一個是因為a[i]權值最大,只有a[i - 1]和a[i + 1]同時選才可能更優,貪心策略。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 500000 + 7; ll a[maxn], l[maxn], r[maxn]; struct node { ll v; int id; bool operator <(node b) const { return v < b.v; } } t; bool flag[maxn]; priority_queue<node> q; int main() { int n, k; cin >> n >> k; for(int i = 1; i <= n; i++) { cin >> t.v; a[i] = t.v; l[i] = i - 1; r[i] = i + 1; t.id = i; q.push(t); } r[0] = 1; l[n] = n + 1; ll ans = 0; while(k--) { while(flag[q.top().id]) q.pop(); t = q.top(); if(t.v < 0) break; q.pop(); ans = ans + t.v; ll x = t.id; flag[l[x]] = flag[r[x]] = 1; a[x] = a[l[x]] + a[r[x]] - a[x]; t.v = a[x]; t.id = x; l[x] = l[l[x]]; r[x] = r[r[x]]; r[l[x]] = x; l[r[x]] = x; q.push(t); } cout << ans << endl; }