小B的农场
题目描述
n
≤
3
∗
1
0
5
n\le3*10^5
n≤3∗105
题目分析
n 2 log n n^2\log n n2logn 的做法是枚举左边界,右边界从大到小枚举,维护中点 y y y 轴相邻两点差的最大值,删掉一个点时加入它上下相邻两点的差,双向链表实现。
n
log
n
n\log n
nlogn 做法:
因为是整点,答案至少为
2
∗
(
max
(
W
,
H
)
+
1
)
2*(\max(W,H)+1)
2∗(max(W,H)+1),所以答案矩形一定经过
x
=
W
2
x=\frac W2
x=2W 或
y
=
H
2
y=\frac H2
y=2H 其中一条直线。(否则只能框在四分之一区域内)
假设经过 x = W 2 x=\frac W2 x=2W 这条线,将点按 y y y 从小到大排序,枚举矩形的上边界,维护每个矩形下边界对应的最宽宽度,越往下显然越窄,可以用单调栈+线段树区间加维护。
实现上,左右分别需要一个单调栈,每个左边的点会对它下面的下边界框出一个左边界(不包括自己),线段树的初值是每个点的
−
y
-y
−y,加上附加的宽度后取 max,再与当前的上边界
y
y
y 相加即为答案。
y
y
y 相等的几个点并不需要特殊处理,与下面的答案会在第一个点统计到,其它点正常框即可。
Code:
#include<bits/stdc++.h>
#define maxn 300005
using namespace std;
int n,W,H,ans;
struct node{
int x,y;
bool operator < (const node &p)const{return y<p.y;}
}a[maxn];
#define lc i<<1
#define rc i<<1|1
int mx[maxn<<2],tag[maxn<<2];
void build(int i,int l,int r){
tag[i]=0;
if(l==r) return void(mx[i]=W-a[l].y);
int mid=(l+r)>>1;
build(lc,l,mid),build(rc,mid+1,r);
mx[i]=max(mx[lc],mx[rc]);
}
void ins(int i,int l,int r,int x,int y,int v){
if(x>r||y<l) return;
if(x<=l&&r<=y) {mx[i]+=v,tag[i]+=v;return;}
int mid=(l+r)>>1;
ins(lc,l,mid,x,y,v),ins(rc,mid+1,r,x,y,v);
mx[i]=max(mx[lc],mx[rc])+tag[i];
}
int A[maxn],An,B[maxn],Bn;
void solve(){
sort(a+1,a+1+n);
build(1,0,n-1),An=Bn=0;
for(int i=1;i<=n;i++){
ans=max(ans,a[i].y+mx[1]);
if(a[i].x<=W/2){
ins(1,0,n-1,A[An],i-1,-a[i].x);
while(An&&a[A[An]].x<a[i].x) ins(1,0,n-1,A[An-1],A[An]-1,-a[i].x+a[A[An]].x),An--;
A[++An]=i;
}
else{
ins(1,0,n-1,B[Bn],i-1,a[i].x-W);
while(Bn&&a[B[Bn]].x>a[i].x) ins(1,0,n-1,B[Bn-1],B[Bn]-1,a[i].x-a[B[Bn]].x),Bn--;
B[++Bn]=i;
}
}
}
int main()
{
//freopen("farm.in","r",stdin);
//freopen("farm.out","w",stdout);
scanf("%d%d%d",&W,&H,&n);
for(int i=1;i<=n;i++) scanf("%d%d",&a[i].x,&a[i].y);
a[++n]=(node){W,H};
solve();
for(int i=1;i<=n;i++) swap(a[i].x,a[i].y);
swap(W,H),solve();
printf("%d\n",ans*2);
}
LOJ#2773. 「ROI 2017 Day 2」学习轨迹
Code:
#include<bits/stdc++.h>
#define maxn 500005
#define LL long long
using namespace std;
char cb[1<<20],*cs,*ct;
#define getc() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<20,stdin),cs==ct)?0:*cs++)
template<class T>inline void read(T &a){
char c;while(!isdigit(c=getc()));
for(a=c-'0';isdigit(c=getc());a=a*10+c-'0');
}
int n,m,a[maxn],b[maxn],c[maxn*2],p[maxn],pn,al,ar,bl,br,pos[maxn],A[maxn],An,B[maxn],Bn;//A[0],B[0] are used as 0!
LL ans,x[maxn],y[maxn];
LL mx[maxn<<2],tag[maxn<<2];
void build(int i,int l,int r,LL x,LL *y){
tag[i]=0;
if(l==r) return void(mx[i]=x-y[p[l]]);
int mid=(l+r)>>1;
build(i<<1,l,mid,x,y),build(i<<1|1,mid+1,r,x,y);
mx[i]=max(mx[i<<1],mx[i<<1|1]);
}
void mdf(int i,int l,int r,int x,int y,LL v){
if(x<=l&&r<=y) {mx[i]+=v,tag[i]+=v;return;}
int mid=(l+r)>>1;
if(x<=mid) mdf(i<<1,l,mid,x,y,v);
if(y>mid) mdf(i<<1|1,mid+1,r,x,y,v);
mx[i]=max(mx[i<<1],mx[i<<1|1])+tag[i];
}
int find(int i,int l,int r){
if(l==r) return l;
int mid=(l+r)>>1;
if(mx[i]==mx[i<<1]+tag[i]) return find(i<<1,l,mid);
else return find(i<<1|1,mid+1,r);
}
inline void updans(LL x,int a,int b,int c,int d,bool flg){
if(flg) swap(a,c),swap(b,d);
if(x>ans) ans=x,al=a,ar=b,bl=c,br=d;
}
void solve(int n,int m,int *a,int *b,LL *x,LL *y,bool flg){
int mid=lower_bound(x+1,x+1+n,x[n]>>1)-x; pn=0;
for(int i=1;i<=m;i++) if(b[i]) p[++pn]=i,pos[pn]=b[i]; p[pn+1]=m+1;
build(1,0,pn,x[n],y);
for(int i=An=Bn=0;i<=pn;i++){
if(i){
if(pos[i]<=mid){
mdf(1,0,pn,A[An],i-1,-x[pos[i]]);
while(An&&pos[i]>pos[A[An]]) mdf(1,0,pn,A[An-1],A[An]-1,-x[pos[i]]+x[pos[A[An]]]),--An;
A[++An]=i;
}
else{
mdf(1,0,pn,B[Bn],i-1,-x[n]+x[pos[i]-1]);
while(Bn&&pos[i]<pos[B[Bn]]) mdf(1,0,pn,B[Bn-1],B[Bn]-1,-x[pos[B[Bn]]-1]+x[pos[i]-1]),--Bn;
B[++Bn]=i;
}
}
if(y[p[i+1]-1]+mx[1]>ans){
int k=find(1,0,pn);
int l=upper_bound(A+1,A+1+An,k)-A; l = l<=An?b[p[A[l]]]+1:1;
int r=upper_bound(B+1,B+1+Bn,k)-B; r = r<=Bn?b[p[B[r]]]-1:n;
updans(y[p[i+1]-1]+mx[1],l,r,p[k]+1,p[i+1]-1,flg);
}
}
}
int main()
{
read(n),read(m);
for(int i=1;i<=n;i++) read(a[i]);
for(int i=1;i<=n;i++) read(x[i]),x[i]+=x[i-1];
for(int i=1;i<=m;i++) read(b[i]);
for(int i=1;i<=m;i++) read(y[i]),y[i]+=y[i-1];
updans(x[n],1,n,0,0,0),updans(y[m],0,0,1,m,0);
for(int i=1;i<=m;i++) c[b[i]]=i,b[i]=0;
for(int i=1;i<=n;i++) a[i]=c[a[i]],b[a[i]]=i;
solve(n,m,a,b,x,y,0),solve(m,n,b,a,y,x,1);
printf("%lld\n%d %d\n%d %d\n",ans,al,ar,bl,br);
}