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;
}
posted @ 2021-05-26 22:28  WWW~~~  阅读(128)  评论(0编辑  收藏  举报