[uoj386][UNR #3]鴿子固定器【貪心】
阿新 • • 發佈:2019-01-03
【題目連結】
http://uoj.ac/problem/386
【題解】
考慮先把序列按排序後,將從小到大從中刪去,刪去時用包含它的區間更新答案。
為什麼答案一定是一段區間:由於數列中剩下的數沒有比當前數更小的。用反證法,如果不是一段區間,那麼把當前點替換為區間隔開的點答案不會變劣。
時間複雜度
【程式碼】
/* - - - - - - - - - - - - - - -
User : VanishD
problem : [UNR3Day1T1]
Points :
- - - - - - - - - - - - - - - */
# include <bits/stdc++.h>
# define ll long long
# define N 200010
using namespace std;
const int inf = 0x3f3f3f3f, INF = 0x7fffffff;
const ll infll = 0x3f3f3f3f3f3f3f3fll, INFll = 0x7fffffffffffffffll;
int read(){
int tmp = 0, fh = 1; char ch = getchar();
while (ch < '0' || ch > '9' ){ if (ch == '-') fh = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9'){ tmp = tmp * 10 + ch - '0'; ch = getchar(); }
return tmp * fh;
}
struct Node{ll s, v;}p[N];
bool cmp(Node x, Node y){return x.s < y.s;}
priority_queue <ll, vector<ll>, greater<ll> > hp;
int n, m, S, V;
ll ans;
void chkans(ll sum, ll det){
ll num1, num2;
if (V == 1) num1 = sum; else num1 = sum * sum;
if (S == 1) num2 = det; else num2 = det * det;
ans = max(ans, num1 - num2);
}
int main(){
n = read(), m = read(), S = read(), V = read();
for (int i = 1; i <= n; i++)
p[i].s = read(), p[i].v = read();
sort(p + 1, p + n + 1, cmp);
ans = -INFll;
for (int i = 1; i <= n; i++){
while (hp.size() > 0) hp.pop();
ll now = 0;
for (int j = i; j <= n; j++){
if (hp.size() == m){
if (hp.top() < p[j].v){
now = now - hp.top() + p[j].v;
hp.pop();
hp.push(p[j].v);
}
}
else {
now = now + p[j].v;
hp.push(p[j].v);
}
chkans(now, p[j].s - p[i].s);
}
}
printf("%lld\n", ans);
return 0;
}