[gym102979H]Hotspot-2
记$\Delta x_{i}=x_{i+1}-x_{i}$,并定义$\Delta x_{0}=\Delta x_{n}=\infty$
以$i$为右端点,记$rs_{j}=\begin{cases}\min(\Delta x_{i},\Delta x_{i-1})&j=i\\ \Delta x_{j}-rs_{j+1}&j<i\end{cases}$
取最大的$j$使得$rs_{j}>\Delta x_{j-1}$或$rs_{j}>rs_{j+1}$,并对$\forall k\in (j,i],R_{k}$中加入$rs_{k}$
以$i$为左端点,做类似地过程(在同一个$R_{i}$中)
结论1:存在一组最优解,满足$\forall 1\le i\le n,r_{i}\in R_{i}$
证明参考这篇论文
结论2:$\sum_{i=1}^{n}|R_{i}|=o(n)$(不需要去重)
将其划分为若干$\Delta x$不下降的极长段,对$i$是否为某段右端点分类讨论:
1.若$i$不是某段右端点,注意到$\Delta x_{i}\le \Delta x_{i+1}$,代入可得$rs_{i-2}>rs_{i-1}$,即仅新增$o(1)$个元素
2.若$i$是某段右端点,假设该段左端点为$i_{l}$,注意到$\Delta x_{i_{0}-1}>\Delta x_{i_{0}}$
若其新增多于$o(i-i_{0})$个元素,即有$rs_{i_{0}-2}\le rs_{i_{0}-1}\le rs_{i_{0}}$,代入$rs_{i_{0}-2}$和$rs_{i_{0}-1}$的式子得矛盾
同时,显然$\sum o(1)+\sum o(i-i_{0})=o(n)$,即得证
结合上述两个结论,令$f_{i,r}$表示前$i$个圆且第$i$个圆半径为$r$的答案,双指针转移即可
时间复杂度为$o(n\log n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 300005 4 #define ll long long 5 vector<int>v[N]; 6 int n,x[N],dx[N],rs[N]; 7 ll ans,g[N],f[N]; 8 ll sqr(int x){ 9 return (ll)x*x; 10 } 11 int main(){ 12 scanf("%d",&n); 13 for(int i=1;i<=n;i++)scanf("%d",&x[i]); 14 dx[0]=dx[n]=1e9; 15 for(int i=1;i<n;i++)dx[i]=x[i+1]-x[i]; 16 for(int i=1;i<=n;i++){ 17 int r=min(dx[i],dx[i-1]); 18 v[i].push_back(r); 19 for(int j=i-1;j;j--){ 20 int r0=dx[j]-r; 21 if ((r0>dx[j-1])||(r0>r))break; 22 r=r0,v[j].push_back(r); 23 } 24 } 25 for(int i=n;i;i--){ 26 int r=min(dx[i],dx[i-1]); 27 v[i].push_back(r); 28 for(int j=i+1;j<=n;j++){ 29 int r0=dx[j-1]-r; 30 if ((r0>dx[j])||(r0>r))break; 31 r=r0,v[j].push_back(r); 32 } 33 } 34 for(int i=1;i<=n;i++)sort(v[i].begin(),v[i].end()); 35 for(int j=0;j<v[1].size();j++)f[j]=sqr(v[1][j]); 36 for(int i=1;i<n;i++){ 37 for(int j=0;j<v[i].size();j++)g[j]=f[j]; 38 ll mx=0; 39 for(int j=v[i+1].size()-1,k=0;j>=0;j--){ 40 while ((k<v[i].size())&&(v[i][k]<=dx[i]-v[i+1][j]))mx=max(mx,g[k++]); 41 f[j]=mx+sqr(v[i+1][j]); 42 } 43 } 44 for(int j=0;j<v[n].size();j++)ans=max(ans,f[j]); 45 printf("%lld\n",ans); 46 return 0; 47 }