洛谷 P1484 種樹
Description
- cyrcyr今天在種樹,他在一條直線上挖了n個坑。這n個坑都可以種樹,但爲了保證每一棵樹都有充足的養料,cyrcyr不會在相鄰的兩個坑中種樹。而且由於cyrcyr的樹種不夠,他至多會種k棵樹。假設cyrcyr有某種神能力,能預知自己在某個坑種樹的獲利會是多少(可能爲負),請你幫助他計算出他的最大獲利。
Input
第一行,兩個正整數n,k。
第二行,n個正整數,第i個數表示在直線上從左往右數第i個坑種樹的獲利。
Output
- 輸出1個數,表示cyrcyr種樹的最大獲利。
Sample Input
6 3 100 1 -1 100 1 -1
Sample Output
200
Data Size
對於20%的數據,n<=20。
對於50%的數據,n<=6000。
對於100%的數據,n<=500000,k<=n/2,在一個地方種樹獲利的絕對值在1000000以內。
題解:
- 這題跟數據備份這題原理相同。都是利用數學歸納法。
#include <iostream>
#include <cstdio>
#include <set>
#define N 500005
#define int long long
using namespace std;
struct Node
{
int pos, val;
friend bool operator < (Node x, Node y) {
if(x.val == y.val) return x.pos < y.pos;
return x.val > y.val;
}
};
int n, k, ans;
int a[N], l[N], r[N];
set<Node> st;
int read()
{
int x = 0, f = 1; char c = getchar();
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return x *= f;
}
signed main()
{
cin >> n >> k;
for(int i = 1; i <= n; i++)
{
a[i] = read();
st.insert((Node){i, a[i]});
l[i] = i - 1, r[i] = i + 1;
}
a[0] = a[n + 1] = -0x3f3f3f3f;
for(int i = 1; i <= k; i++)
{
int val = (*st.begin()).val;
int pos = (*st.begin()).pos;
if(val <= 0) {cout << ans; return 0;}
ans += val;
//刪掉堆中的pos和l[pos]和r[pos]
st.erase(st.begin());
st.erase((Node){l[pos], a[l[pos]]});
st.erase((Node){r[pos], a[r[pos]]});
//添加新元素
a[pos] = a[l[pos]] + a[r[pos]] - a[pos];
st.insert((Node){pos, a[pos]});
l[pos] = l[l[pos]], r[l[pos]] = pos;
r[pos] = r[r[pos]], l[r[pos]] = pos;
}
cout << ans;
return 0;
}