http://www.elijahqi.win/archives/3952
考慮枚舉每個右端點 然後可以用一個堆維護區間最小值 然後當我們發現我們如果把枚舉的右端點都彈出的時候一定break因爲剩下的我們可以簡單通過左移右端點使得答案變成更優的
另外我們可以用一個鏈表維護如果這個節點在這次i加入的時候並沒有被加入那麼說明之後我再被加入的時候一定不會被加入 因爲我右端點在右移 所以說我至少應該已經有了m個滿足條件的點我繼續使用那滿足條件的m個點即可
pow 竟然炸精度 我wtf!!!
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline char gc(){
static char now[1<<16],*S,*T;
if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
return *S++;
}
inline int read(){
int x=0,f=1;char ch=gc();
while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}
while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
return x*f;
}
const int N=2e5+10;
struct node{
int s,v;
}data[N];
int n,m,ds,dv,pre[N];
inline bool cmp(const node &a,const node &b){return a.s<b.s;}
inline ll update(ll x,ll y){
x=dv==2?x*x:x;y=ds==2?y*y:y;return x-y;
}
int main(){
freopen("uoj386.in","r",stdin);
n=read();m=read();ds=read();dv=read();ll ans=0;
for (int i=1;i<=n;++i) data[i].s=read(),data[i].v=read(),pre[i]=i-1;
sort(data+1,data+n+1,cmp);
for (int i=1;i<=n;++i){
priority_queue<int,vector<int>,greater<int> >q;
for (int j=1;j<=m;++j) q.push(0);int now=i,last=0;ll sum=0;
while(now){
int y=q.top();
if (data[now].v>y){
sum+=data[now].v-y;q.pop();q.push(data[now].v);
if (q.top()>data[i].v) break;
ans=max(ans,update(sum,data[i].s-data[now].s));
pre[last]=now;last=now;
}now=pre[now];
}pre[last]=now;
}printf("%lld\n",ans);
return 0;
}