CF 713 E 贪心题解
CF 713 E 贪心题解
发现这题大多数做法都是dp的。
我讲一个贪心的做法。
首先破环为链的部分dp的做法也有涉及,就不讲了。
下面就是给你一些点\(p_1,p_2...p_n\),从每一个点向左或向有扩展\(d\),然后完全覆盖圆
首先枚举最后那个往右延申的点\(p_i\)
然后就变成了链上覆盖问题了。
从前到后扫描点,假设当前考虑了\(p_i\),然后前面覆盖到了\(T\) 。
若\(T+1\geq p_i\),则\(i\)一定向右扩展,\(T\leftarrow p_i+d\)。
否则若\(T+1<p_{i+1}-d\),所以\(p_i\)必须向左延申,\(T\leftarrow p_i\)。
否则若\(p_{i+1}=p_i\),则\(T\leftarrow p_i\)。
否则\(T\leftarrow p_{i}+d,i++(用p_{i+1}来覆盖[T+1,p_{i-1}],然后p_i向右扩展)\) 。
这样看似是\(O(N^2\log N)\),不过速度甚至超过了正常的\(O(N\log N)\)。
code:Submission #117173559 - Codeforces
/*
{
######################
# Author #
# Gary #
# 2021 #
######################
*/
#include<bits/stdc++.h>
#define rb(a,b,c) for(int a=b;a<=c;++a)
#define rl(a,b,c) for(int a=b;a>=c;--a)
#define LL long long
#define IT iterator
#define PB push_back
#define II(a,b) make_pair(a,b)
#define FIR first
#define SEC second
#define FREO freopen("check.out","w",stdout)
#define rep(a,b) for(int a=0;a<b;++a)
#define SRAND mt19937 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(a) rng()%a
#define ALL(a) a.begin(),a.end()
#define POB pop_back
#define ff fflush(stdout)
#define fastio ios::sync_with_stdio(false)
#define check_min(a,b) a=min(a,b)
#define check_max(a,b) a=max(a,b)
using namespace std;
inline int read(){
int x=0;
char ch=getchar();
while(ch<'0'||ch>'9'){
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x;
}
const int INF=0x3f3f3f3f;
typedef pair<int,int> mp;
/*}
*/
const int MAXN=1e5+233;
int a[MAXN],n,m;
vector<int> cyc;
bool check(int x){
int fst=INF;
rb(z,1,n){
bool ok=true;
int need=m-a[n-z+1]-x;
if(need>x) break;
int to=1-need;
rb(i,1,n){
if(a[i]<=to){
to=a[i]+x+1;
continue;
}
if(i!=n-z&&i!=n&&a[i+1]-x<=to&&a[i+1]!=a[i]+1){
to=a[i]+x+1;
i++;
continue;
}
if(a[i]-x<=to&&i!=n-z+1){
to=a[i]+1;
continue;
}
else{
break;
}
}
if(to>=min(a[n-z+1],fst)&&ok) return true;
check_min(fst,a[n-z+1]-x);
}
return false;
}
int main(){
scanf("%d",&m);
scanf("%d",&n);
rb(i,1,n) a[i]=read();
sort(a+1,a+1+n);
int l=0,r=0;
rb(i,1,n-1) cyc.PB(a[i+1]-a[i]-1);
cyc.PB(m-a[n]+a[1]-1);
vector<int> Tmp;
r=*max_element(ALL(cyc));
int z=0;
rb(i,0,n-1) if(cyc[i]==r){
z=i;
break;
}
rb(i,z+1,n-1) Tmp.PB(cyc[i]);
rb(i,0,z) Tmp.PB(cyc[i]);
cyc=Tmp;
a[1]=1;
rb(i,2,n) a[i]=a[i-1]+cyc[i-2]+1;
assert(a[n]+cyc.back()==m);
while(l<r){
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
printf("%d\n",l);
return 0;
}