題目鏈接: https://codeforces.com/contest/1221/problem/F
題意:
二維平面上有 個帶權值的點,選擇一個 的一個正方形區域獲得的權值是該區域內點權的和減去正方形邊長。 現在要你選擇一個值最大的區域,輸出最大權值 和選擇的範圍 和 。
做法:
這種枚舉做法其實已經碰到好多次了,之前網絡賽也有一場類似的從後向前枚舉,然後不斷更新值的做法。
先跟着比較專業的大佬題解的做法說,因爲如果我們要選擇一個點 ,那麼一定是我們選擇的區間 滿足 這樣的條件的,所以我們完全可以把這個二維空間轉化爲一維來做。
將 和 中的較小值先記錄下來(如 ,那麼這個點我們就在枚舉到 的時候再做),從大到小去枚舉要做的這個值,拿到這個點之後,我們就要在區間 上去更新這個點,因爲我們這個較小的值被枚舉到後,這個點的左區間就已經被包括了,所以從這個點的右區間開始都要更新。
至於減去邊長的問題我們可以在一開始的時候就先build好,在枚舉值的時候,這個值之前的長度被加上,就可以把邊長問題解決掉了。
代碼
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i = (int)a;i<=(int)b;i++)
#define pb push_back
#define lson rt<<1
#define rson rt<<1|1
#define mid (l+r)/2
using namespace std;
const int maxn=500005;
const int maxm=1000055;
typedef long long ll;
int n,x[maxn],y[maxn],tmp[maxm],ct,mxd[maxm<<2];
ll ansl,ansr,ans,mx[maxm<<2],laz[maxm<<2],tans,tid,v[maxn];
vector<int> id[maxm];
void push_up(int rt){
if(mx[lson]>=mx[rson]) mx[rt]=mx[lson],mxd[rt]=mxd[lson];
else mx[rt]=mx[rson],mxd[rt]=mxd[rson];
}
void build(int l,int r,int rt){
if(l==r){
mx[rt]=-tmp[l];
mxd[rt]=l;
return ;
}
build(l,mid,lson);
build(mid+1,r,rson);
push_up(rt);
}
void deal(int rt,ll v){
laz[rt]+=v; mx[rt]+=v;
}
void push_down(int rt){
if(laz[rt]){
deal(lson,laz[rt]);
deal(rson,laz[rt]);
laz[rt]=0;
}
}
void update(int l,int r,int rt,int ql,int qr,ll v){
if(ql<=l&&r<=qr){
deal(rt,v);
return ;
}
push_down(rt);
if(mid>=ql) update(l,mid,lson,ql,qr,v);
if(mid<qr) update(mid+1,r,rson,ql,qr,v);
push_up(rt);
}
void query(int l,int r,int rt,int ql,int qr){
if(ql<=l&&r<=qr){
if(mx[rt]>tans) tans=mx[rt],tid=mxd[rt];
return ;
}
push_down(rt);
if(mid>=ql) query(l,mid,lson,ql,qr);
if(mid<qr) query(mid+1,r,rson,ql,qr);
}
int main(){
scanf("%d",&n);
rep(i,1,n){
scanf("%d%d%lld",&x[i],&y[i],&v[i]);
if(x[i]>y[i]) swap(x[i],y[i]);
tmp[++ct]=x[i],tmp[++ct]=y[i];
}
sort(tmp+1,tmp+1+ct);
ct=unique(tmp+1,tmp+1+ct)-tmp-1;
rep(i,1,n){
x[i]=lower_bound(tmp+1,tmp+1+ct,x[i])-tmp;
y[i]=lower_bound(tmp+1,tmp+1+ct,y[i])-tmp;
id[x[i]].push_back(i);
}
build(1,ct,1);
ans=0; ansl=tmp[ct]+1,ansr=tmp[ct]+1;
for(int i=ct;i>=1;i--){
for(auto u:id[i]){
update(1,ct,1,y[u],ct,v[u]);
}
tans=-1e9;
query(1,ct,1,i,ct);
if(ans<tans+tmp[i]){
ans=tans+tmp[i];
ansl=tmp[i],ansr=tmp[tid];
}
}
printf("%lld\n%lld %lld %lld %lld\n",ans,ansl,ansl,ansr,ansr);
return 0;
}