CF990 E Post Lamps

2018-05-31  本文已影响0人  wygz

CF990 E Post Lamps

[ 原题链接 ] http://codeforces.com/contest/990/problem/E

不同的区间长度 $$i$$ 的价格不同、需要的区间个数也不同,不满足二分或三分的特性,因此需要枚举 $$i$$。

在确定 $$i$$ 以后,pos 从 0 开始划分区间,区间必须覆盖 0 ~ n 的所有段(可以重复放)。

如果遇到 pos 不可以放灯,那么 pos 往回走到第一个可以放灯的位置。$$O(n)$$ 预处理上一个可以放灯的位置。

直到 pos 走到 n,或者遇到 pos+1 ~ pos+$$ i $$ 均不可放灯的情况,这样尽量往后放、少放灯的贪心是最优的。

而当 $$i$$ 小于最长连续一段不可放灯的长度时,最长的那段是无法覆盖全的。

因此进一步缩小了 $$i$$ 的枚举范围,经测试时限 $$4.5s$$ 可以 AC。

#include <bits/stdc++.h>
using namespace std;
template <typename T> void read(T &t) {
    char ch=getchar(); int f=1; t=0;
    while ('0'>ch||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
    do { (t*=10)+=ch-'0'; ch=getchar(); } while ('0'<=ch&&ch<='9'); t*=f;
}
typedef long long ll;
const int maxn=1000010;
int n,m,k,mx,cnt[maxn];
bool d[maxn];
ll s[maxn],ans=1LL<<60;
int main() {
    read(n); read(m); read(k);
    for (int i=1;i<=m;i++) {
        int x; read(x);
        d[x]=1;
    }
    if (d[0]) { printf("-1\n"); return 0; }
    for (int i=0;i<n;i++) {
        if (!d[i]) continue;
        cnt[i]=1; if (i) cnt[i]+=cnt[i-1];
        mx=max(mx,cnt[i]);
    }
    for (int i=1;i<=k;i++) read(s[i]);
    for (int i=mx;i<=k;i++) {
        int pos=0,cntcnt=0;
        while (pos<n) {
            if (d[pos]) {
                if (cnt[pos]==i) break;
                pos-=cnt[pos];
            } else {
                cntcnt++;
                pos+=i;
            }
        }
        if (pos>=n) ans=min(ans,s[i]*cntcnt);
    }
    if (ans>=1LL<<60) ans=-1;
    printf("%I64d\n",ans);
    return 0;
}
上一篇下一篇

猜你喜欢

热点阅读