题解:(假设最底层的是1)不难发现每次把某个
j
+
1
…
i
j+1\dots i
j+1…i放上去,必须要有
1
…
i
1\dots i
1…i是合法的,那么
∀
j
∈
[
1
,
i
]
,
j
…
i
\forall j\in[1,i],j\dots i
∀j∈[1,i],j…i都是合法的。
然后一坨木板的加权重心是
∑
i
x
i
m
i
∑
i
m
i
\frac{\sum_{i}x_im_i}{\sum_{i}m_i}
∑imi∑iximi,也就是
j
+
1
…
i
j+1\dots i
j+1…i合法等价于
∑
j
<
k
≤
i
(
R
k
+
L
k
)
(
R
k
−
L
k
)
2
∑
j
<
k
≤
i
(
R
k
−
L
k
)
=
A
i
−
A
j
B
i
−
B
j
∈
[
L
j
,
R
j
]
\frac{\sum_{j<k\le i}(R_k+L_k)(R_k-L_k)}{2\sum_{j<k\le i}(R_k-L_k)}=\frac{A_i-A_j}{B_i-B_j}\in[L_j,R_j]
2∑j<k≤i(Rk−Lk)∑j<k≤i(Rk+Lk)(Rk−Lk)=Bi−BjAi−Aj∈[Lj,Rj]
以
A
i
−
A
j
B
i
−
B
j
≤
R
j
\frac{A_i-A_j}{B_i-B_j}\le R_j
Bi−BjAi−Aj≤Rj为例,其等价于
A
i
≤
R
j
B
i
−
R
j
B
j
+
A
j
=
F
R
j
(
B
i
)
A_i\le R_jB_i-R_jB_j+A_j=FR_j(B_i)
Ai≤RjBi−RjBj+Aj=FRj(Bi),那么将
F
R
1
(
x
)
…
F
R
i
−
1
(
x
)
FR_1(x)\dots FR_{i-1}(x)
FR1(x)…FRi−1(x)在
B
i
B_i
Bi处的点值求出来取最小值和
A
i
A_i
Ai比较一下即可,这个可以用李超线段树做。
最后答案显然就是相邻一对合法的差的最大值。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
const lint INF=LLONG_MAX;const int N=100010;
int L[N],R[N];lint A[N];int B[N];
struct Line{
lint k,b;Line(lint _k=0,lint _b=0) { k=_k,b=_b; }
inline lint operator() (lint x) { return k*x+b; }
};
struct segment{
Line f;segment *ch[2];
}*rtL,*rtR;
inline lint query(segment* &rt,int l,int r,int p)
{
if(rt==NULL) return INF;lint v=rt->f(p);
if(l==r) return v;int mid=l+(r-l)/2;
if(p<=mid) return min(v,query(rt->ch[0],l,mid,p));
else return min(v,query(rt->ch[1],mid+1,r,p));
}
inline int update(segment* &rt,int l,int r,Line f)
{
if(rt==NULL) return rt=new segment,rt->ch[0]=rt->ch[1]=NULL,rt->f=f,0;
int mid=l+(r-l)/2;if(rt->f(l)>f(l)) swap(rt->f,f);if(rt->f(r)<=f(r)) return 0;
if(rt->f(mid)<=f(mid)) return update(rt->ch[1],mid+1,r,f);
else return swap(rt->f,f),update(rt->ch[0],l,mid,f);return 0;
}
int main()
{
int n=inn(),las=0,ans=0;rtL=NULL,rtR=NULL;
rep(i,1,n) L[i]=inn(),R[i]=inn();
reverse(L+1,L+n+1),reverse(R+1,R+n+1);
rep(i,1,n) A[i]=A[i-1]+R[i]*R[i]-L[i]*L[i];
rep(i,1,n) B[i]=B[i-1]+2*(R[i]-L[i]);
rep(i,1,n)
{
lint fL=query(rtL,1,B[n],B[i]),fR=query(rtR,1,B[n],B[i]);
if(A[i]<=fR&&-A[i]<=fL) ans=max(ans,i-las),las=i;
update(rtL,1,B[n],Line(-L[i],(lint)L[i]*B[i]-A[i]));
update(rtR,1,B[n],Line(R[i],-(lint)R[i]*B[i]+A[i]));
}
return !printf("%d\n",max(ans,n-las));
}