F. Choose a Square
题意:
输入 n ( 1 ≤ n ≤ 5 e 5 ) n(1\leq n\leq5e5) n(1≤n≤5e5),表示有 n n n个点,接下来 n n n行,每行 x i , y i , c i ( 0 ≤ x i , y i ≤ 1 0 9 , − 1 0 6 ≤ c i ≤ 1 0 6 ) x_i,y_i,c_i(0\leq x_i,y_i\leq10^9,-10^6\leq c_i\leq10^6) xi,yi,ci(0≤xi,yi≤109,−106≤ci≤106)。要求选取一个对角线再 y = x y=x y=x上的一个正方形,使得正方形围成的 ( ∑ c i ) − l ( 正 方 形 边 长 ) (\sum c_i)-l(正方形边长) (∑ci)−l(正方形边长)最大。
题解:
首先分析对于一个点
(
x
,
y
)
(x,y)
(x,y)来说如何使他被正方形(左下角
(
l
,
l
)
(l,l)
(l,l),右上角
(
r
,
r
)
(r,r)
(r,r))包含,其实只要满足
l
≤
m
i
n
(
x
,
y
)
≤
m
a
x
(
x
,
y
)
≤
r
l \leq min(x,y)\leq max(x,y)\leq r
l≤min(x,y)≤max(x,y)≤r,那么不妨使所有的点
x
≤
y
x\leq y
x≤y,这样只要使
l
≤
x
≤
y
≤
r
l\leq x\leq y \leq r
l≤x≤y≤r。
然后把
x
,
y
,
c
x,y,c
x,y,c按
x
x
x从小到大排序,接下来扫一遍
x
x
x,查询更新线段树就好。
线段树维护的是
p
a
i
r
pair
pair(最大值,最大值所对应的下标);初始化线段树,一开始先把所有的
−
r
-r
−r加入线段树,对于
x
x
x更新
y
−
m
a
x
n
y-maxn
y−maxn加
c
c
c,这样维护的就是
m
a
x
(
(
∑
c
)
−
r
)
max((\sum c)-r)
max((∑c)−r),再把固定的
l
l
l加上就是固定
l
l
l时最大的答案。
时间复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn)
代码:
#include<bits/stdc++.h>
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
#define ll long long
#define P pair<ll,ll>
using namespace std;
const int N=5e5+9;
int n;
struct T{int x,y,c;}a[N];
int x[N],nx;
ll ans,z,y;
bool cmp(T t1,T t2){return t1.x<t2.x;}
inline int getid(int y){return lower_bound(x+1,x+nx+1,y)-x;}
ll add[N<<2];
P mx[N<<2];
void push_down(int p){
if(add[p]){
add[ls(p)]+=add[p],add[rs(p)]+=add[p];
mx[ls(p)].first+=add[p],mx[rs(p)].first+=add[p];
add[p]=0;
}
}
void push_up(int p){mx[p]=max(mx[ls(p)],mx[rs(p)]);}
void update(int p,int l,int r,int ql,int qr,int qz){
if(ql<=l&&r<=qr){mx[p].first+=qz,add[p]+=qz;if(l==r)mx[p].second=l;}
else{
push_down(p);
int mid=(l+r)>>1;
if(ql<=mid)update(ls(p),l,mid,ql,qr,qz);
if(qr>mid)update(rs(p),mid+1,r,ql,qr,qz);
push_up(p);
// cout<<"yu"<<p<<" "<<mx[p].first<<" "<<mx[p].second<<endl;
}
}
P query(int p,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return mx[p];
else{
push_down(p);
int mid=(l+r)>>1;
P ans=P(-2e9,0);
if(ql<=mid)ans=query(ls(p),l,mid,ql,qr);
if(qr>mid)ans=max(ans,query(rs(p),mid+1,r,ql,qr));
// cout<<"tu"<<p<<" "<<ans.first<<" "<<ans.second<<endl;
return ans;
}
}
/*void query(int p,int l,int r,int qx){
if(l==r)cout<<"pu"<<l<<" "<<p<<" "<<mx[p].first<<" "<<mx[p].second<<endl;
else{
push_down(p);
int mid=(l+r)>>1;
query(ls(p),l,mid,qx);
query(rs(p),mid+1,r,qx);
cout<<"pu"<<p<<" "<<mx[p].first<<" "<<mx[p].second<<endl;
}
}*/
int main(){
// freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i].x>>a[i].y>>a[i].c;
if(a[i].x>a[i].y)swap(a[i].x,a[i].y);
x[++nx]=a[i].y;
}
sort(a+1,a+n+1,cmp);
// for(int i=1;i<=n;i++)cout<<a[i].x<<" "<<a[i].y<<" "<<a[i].c<<endl;
sort(x+1,x+nx+1),nx=unique(x+1,x+nx+1)-x-1;
for(int i=1;i<=nx;i++)update(1,1,nx,i,i,-x[i]);
for(int i=1;i<=n;i++)update(1,1,nx,getid(a[i].y),nx,a[i].c);
//query(1,1,nx,1);
// for(int i=1;i<=nx;i++)cout<<query(1,1,nx,i).first<<" "<<query(1,1,nx,i).second<<endl;
z=y=2e9;
for(int i=1;i<=n;i++){
// query(1,1,nx,1);
P zd=query(1,1,nx,getid(a[i].x),nx);
// cout<<"---"<<zd.first<<" "<<zd.second<<endl;
// cout<<a[i].x<<endl;
if(ans<zd.first+a[i].x)ans=zd.first+a[i].x,z=a[i].x,y=x[zd.second];
update(1,1,nx,getid(a[i].y),nx,-a[i].c);//cout<<a[i].y<<" "<<nx<<" "<<-a[i].c<<endl;
while(i+1<=n&&a[i+1].x==a[i].x)i++,update(1,1,nx,getid(a[i].y),nx,-a[i].c);//cout<<a[i].y<<" "<<nx<<" "<<-a[i].c<<endl;
}
cout<<ans<<endl;
cout<<z<<" "<<z<<" "<<y<<" "<<y<<endl;
return 0;
}