对于某个点 $(x,y)$ ,不妨设 $x<y$ 因为如果 $x>y$ 直接按 $y=x$ 对称一下即可
当且仅当正方形左下角 $(a,a)$ 满足 $a<=x$,右上角 $(b,b)$ 满足 $b>=y$ ,才能得到这个点的价值
所以发现其实是个二维偏序的问题,直接把 $(a,b)$ 看成另一个平面上的点,$(x,y)$ 放到那个平面上
这样就问题变成选一个点 $(a,b)$ ,你得到的价值为所有 $x>=a$ 并且 $y<=b$ 的点 $(x,y)$ 的价值和再减去 $a,b$ 之间的差值
考虑把点按第一关键字 $x$ 从大到小,按第二关键字 $y$ 从小到大排序,维护一个线段树表示当前 $a=x$ 的情况下 $y$ 取各个值时能够得到的最大价值
因为当前 $a=x$ 的情况下,所有 $x>a$ 的点的代价都加入了,每次加入一个点以后直接查询线段树上 $b>=y$ 和下一个点 $b<=y'-1$ 之间的那一段的最大价值,当然如果下一个点的 $x$ 和当前点不同,那么查询直接查询当前点到线段树最大位置的值即可
发现这样是有问题的,因为对于不同的 $b=y$ ,直接取点的值最大还不行,因为代价还要考虑 $-(y-x)$,所以线段树上维护的应该是点值和再减 $y$ 以后的最大值,当然要随便维护一下取最大值时 $b$ 的值
然后就没了,代码因为主体是比赛时写的,可能比较丑,但是还能看...吧
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=1e6+7; const ll INF=1e18; int n,x[N],y[N],c[N],t[N],xx[N],yy[N]; struct dat { int l,r,val,id; dat (int _l=0,int _r=0,int _val=0,int _id=0) { l=_l,r=_r,val=_val,id=_id; } inline bool operator < (const dat &tmp) const { if(l!=tmp.l) return l>tmp.l; return r!=tmp.r ? r<tmp.r : val>tmp.val; } }d[N]; int tot; int inv[N]; struct SegTree { ll T[N<<2],id[N<<2],tag[N<<2]; inline void pushup(int o) { T[o]=max(T[o<<1],T[o<<1|1]); id[o]=T[o<<1]>=T[o<<1|1] ? id[o<<1] : id[o<<1|1]; } inline void pushdown(int o,int l,int r) { if(!o||!tag[o]) return; T[o]+=tag[o]; if(l==r) { tag[o]=0; return; } tag[o<<1]+=tag[o]; tag[o<<1|1]+=tag[o]; tag[o]=0; } void build(int o,int l,int r) { if(l==r) { id[o]=l; T[o]=-inv[l]; return; } int mid=l+r>>1; build(o<<1,l,mid); build(o<<1|1,mid+1,r); pushup(o); } inline void change(int o,int l,int r,int ql,int qr,int v) { pushdown(o,l,r); if(l>qr||r<ql) return; if(l>=ql&&r<=qr) { tag[o]=v; pushdown(o,l,r); return; } int mid=l+r>>1; change(o<<1,l,mid,ql,qr,v); change(o<<1|1,mid+1,r,ql,qr,v); pushup(o); } ll pos,val; inline void query(int o,int l,int r,int ql,int qr) { pushdown(o,l,r); if(l>qr||r<ql) return; if(l>=ql&&r<=qr) { if(T[o]>val) val=T[o],pos=id[o]; return; } int mid=l+r>>1; query(o<<1,l,mid,ql,qr); query(o<<1|1,mid+1,r,ql,qr); pushup(o); } }ST; int main() { n=read(); for(int i=1;i<=n;i++) xx[i]=x[i]=read(),yy[i]=y[i]=read(),c[i]=read(); for(int i=1;i<=n;i++) t[++tot]=x[i],t[++tot]=y[i]; sort(t+1,t+tot+1); tot=unique(t+1,t+tot+1)-t-1; for(int i=1;i<=n;i++) x[i]=lower_bound(t+1,t+tot+1,x[i])-t; for(int i=1;i<=n;i++) y[i]=lower_bound(t+1,t+tot+1,y[i])-t; int ansx=0,ansy=0; for(int i=1;i<=n;i++) { if(x[i]>y[i]) swap(x[i],y[i]),swap(xx[i],yy[i]); d[i]=dat(x[i],y[i],c[i],i); ansx=max(ansx,yy[i]+1); ansy=max(ansy,yy[i]+1); inv[x[i]]=xx[i]; inv[y[i]]=yy[i]; } sort(d+1,d+n+1); ll ans=0; ST.build(1,1,tot); d[n+1].l=-233; for(int i=1;i<=n;i++) { ST.change(1,1,tot,d[i].r,tot,d[i].val); ST.val=-INF; ST.pos=0; if(d[i].l==d[i+1].l) ST.query(1,1,tot,d[i].r,d[i+1].r-1); else ST.query(1,1,tot,d[i].r,tot); ll res=ST.val+inv[d[i].l]; if(res>ans) ans=res,ansx=inv[d[i].l],ansy=inv[ST.pos]; } printf("%lld\n",ans); printf("%d %d %d %d\n",ansx,ansx,ansy,ansy); return 0; }
来源:博客园
作者:LLTYYC
链接:https://www.cnblogs.com/LLTYYC/p/11556948.html