Automatic Door CodeForces

大意: 一扇自动门, 若$t$时刻有人来, 并且门是关的, 自动门会打开$d$时间, [t,t+d]时刻来的人都可以进入, 现在有n个雇员, 分别在$a, 2a, ..., na$时刻来, $m$个客户, 分别在$t_1, t_2,..., t_m$时刻来, 求自动门打开的次数.

数据范围1 ≤ n, a ≤ 1091 ≤ m ≤ 1051 ≤ d ≤ 1018, 1 ≤ ti ≤ 1018

根据题目的范围, 显然要考虑枚举$m$个客户, 当一个客户$i$来的时候, 先处理$t_i$之前未处理的雇员即可.

为了防止最后还有未处理的雇员, 可以添加一个客户, 让他时间等于n*a, 显然不影响答案. 

#include <iostream>
#include <algorithm>
#include <cstdio>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
using namespace std;
typedef long long ll;


const int N = 1e6+10;
ll n, m, a, d, t[N];
int main() {
	scanf("%lld%lld%lld%lld", &n, &m, &a, &d);
	REP(i,1,m) scanf("%lld", t+i);
	ll now = 0, ans = 0, cur = 1;
	t[++m] = n*a;
	PER(i,2,m) if (t[i]<t[i-1]) swap(t[i],t[i-1]);
	REP(i,1,m) {
		if (cur<=n&&cur*a<t[i]) {
			now = cur*a;
			ll r = d/a+1, tot = (t[i]-now)/a+1;
			ll q = tot/r;
			if (q) {
				ans += q;
				now += (q-1)*r*a+d;
				tot -= q*r;
				cur = now/a+1;
			}
			if (tot) {
				++ans;
				now = cur*a+d;
				cur = now/a+1;
			}
		}
		if (now>=t[i]) continue;
		now = t[i]+d;
		cur = now/a+1;
		++ans;
	}
	printf("%lld
", ans);
}
原文地址:https://www.cnblogs.com/uid001/p/10803332.html