[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 } 
View Code

 

posted @ 2022-02-25 16:11  PYWBKTDA  阅读(121)  评论(1编辑  收藏  举报