Loading [MathJax]/jax/element/mml/optable/BasicLatin.js

[gym102979H]Hotspot-2

Δxi=xi+1xi,并定义Δx0=Δxn=

i为右端点,记rsj={min

取最大的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 @   PYWBKTDA  阅读(141)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示