题目链接: https://codeforces.com/contest/1221/problem/F
题意:
二维平面上有 n n n 个带权值的点,选择一个 [ ( a , a ) , ( b , b ) ] ( a < = b ) [(a,a),(b,b)] (a<=b) [(a,a),(b,b)](a<=b) 的一个正方形区域获得的权值是该区域内点权的和减去正方形边长。 现在要你选择一个值最大的区域,输出最大权值 v v v 和选择的范围 a a a 和 b b b。
做法:
这种枚举做法其实已经碰到好多次了,之前网络赛也有一场类似的从后向前枚举,然后不断更新值的做法。
先跟着比较专业的大佬题解的做法说,因为如果我们要选择一个点 i i i ,那么一定是我们选择的区间 [ l , r ] [l,r] [l,r] 满足 l < = m i n ( x [ i ] , y [ i ] ) , r > = m a x ( x [ i ] , y [ i ] ) l<=min(x[i],y[i]),r>=max(x[i],y[i]) l<=min(x[i],y[i]),r>=max(x[i],y[i]) 这样的条件的,所以我们完全可以把这个二维空间转化为一维来做。
将 x [ i ] x[i] x[i] 和 y [ i ] y[i] y[i] 中的较小值先记录下来(如 x = 2 , y = 5 x=2,y=5 x=2,y=5,那么这个点我们就在枚举到 2 2 2 的时候再做),从大到小去枚举要做的这个值,拿到这个点之后,我们就要在区间 [ m a x ( x [ i ] , y [ i ] ) , n u m ] [max(x[i],y[i]),num] [max(x[i],y[i]),num] 上去更新这个点,因为我们这个较小的值被枚举到后,这个点的左区间就已经被包括了,所以从这个点的右区间开始都要更新。
至于减去边长的问题我们可以在一开始的时候就先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;
}