【题目链接】
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;
}