CF883A.Automatic Door Solution
首先,我们做出如下约定:
将整个时间以客人的时间分隔成n段,分别是
\[(a[i-1],a[i]]
\]
,其中第一段是(0,a[1]),最后一段是
\[(a[i],max(a[i],n*a))
\]
由于每一组中的有雇员,雇员的开门可能使得客人不需要开门,因此引入一个last量表示前一组的最后一个开门向后一组延续了多少秒
可以处理出如果是雇员开门,那么包含其在内的之后的
\[tt=d/a+1
\]
个雇员将不需要开门,因此,在每一段内,我们先求出这一段内有多少个雇员,再把这些雇员以tt为一组分成group组
如果这一段内没有雇员,即0组,则直接让res++,last=d
如果有一组或多组(k组),处理思路是记录一个l量,先让l指向k组的开端,若l+d>=r,则说明这一段的右客人不需要开门,且右l+d-r的盈余时间,则last=l+d-r,否则右客人需要开门,res++,last=d
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define int long long
using namespace std;
int n, m, a, d;
vector<int> t;
signed main()
{
cin >> n >> m >> a >> d;
for (int i = 1; i <= m; i++) {
int c;
cin >> c;
t.push_back(c);
}
//排序后去重
sort(t.begin(), t.end());
t.erase(unique(t.begin(), t.end()), t.end());
int m = t.size();
int last = 0, l , r , res = 0;
int tt = d / a + 1;//one can hold
for (int i = 0; i < m; i++) {
r = t[i];
l = (i == 0) ? 0 : t[i - 1];
if (l == r) {
res++;
last = d;
continue;
}
if (last >= r - l) {
last -= r - l;
continue;
}
int hold = min(n, r / a) - min(n, (l + last) / a);
int group = (hold + tt - 1) / tt;
l = ((l + last) / a + 1)*a;
res += (hold + tt - 1) / tt;
if (!group) {
res++, last = d;
continue;
}
if (group == 1) {
if (l + d >= r)last = l + d - r;
else res++, last = d;
continue;
}
l += ((hold%tt==0)?(hold / tt-1):(hold/tt))*tt*a;
l += d;
if (l >= r)last = l - r;
else res++, last = d;
}
if (t[m - 1] + last <= n * a) {
res += ((n - (t[m - 1] + last) / a) + tt - 1) / tt;
}
cout << res;
}
浙公网安备 33010602011771号