链接:
题意:
有
N
个任务,可以在
题解:
不难发现这是个拟阵,所以可以从大到小排序之后贪心。
考虑对于一组区间,如何判断它是否合法也可以贪心:从左到右扫,每个位置安排
r
最小的点,记为
考虑插入一个区间
[x,x]
是否合法,考虑
i
向
举个例子,
x→y→z→∞
的意义就是
x
这个位置放了一个区间,所以原来
每次放完一个区间之后暴力算出哪些合法,用 set 维护一下就好了,详见代码。
复杂度 O(nlogm+m2logm) ,其中 m=max(finishi) 。
代码:
#include <bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
#define mset(x, y) memset(x, y, sizeof x)
#define mcpy(x, y) memcpy(x, y, sizeof x)
using namespace std;
typedef long long LL;
typedef pair <int, int> pii;
const int MAXN = 2005;
const int mod = 1e9 + 7;
class HeroicSchedule
{
int m, ans, rig[MAXN];
vector <int> r[MAXN];
vector <pii> a[MAXN];
set <int> s;
inline void Solve()
{
s.clear();
multiset <int> cur;
for (int i = 0; i < m; i ++)
{
for (auto j : r[i])
cur.insert(j);
if (cur.empty())
rig[i] = m;
else
rig[i] = *cur.begin(), cur.erase(cur.begin());
}
for (int i = m - 1; ~i; i --)
if (rig[i] == m || (!s.empty() && *s.begin() <= rig[i]))
s.insert(i);
}
public:
int getmax(int n, int A, int B, int C, int modStart, int modLen, int modCost)
{
ans = 0;
for (int i = 1, x = A, y, z; i <= n; i ++, x = (1LL * z * B + C) % mod)
y = (1LL * x * B + C) % mod, z = (1LL * y * B + C) % mod, a[z % modCost].pb(mp(x % modStart, y % modLen + x % modStart));
m = modStart + modLen - 1;
for (int i = 0; i < m; i ++)
s.insert(i);
for (int i = modCost - 1; i; i --)
for (auto e : a[i])
if (!s.empty() && *s.rbegin() >= e.xx && *s.lower_bound(e.xx) <= e.yy)
ans += i, r[e.xx].pb(e.yy), Solve();
return ans;
}
};