F
题意
个锅,
个牛排
- 第
个牛排要炸
分钟
- 一个牛排可以拆成两段时间炸,
输出行,每行描述烹饪计划
个三元组
,表示第
个锅,时间从
到
思路
贪心。
考虑一个时间上限,指最后一块牛排煎完那一刻的时间。
- 首先要考虑每一块牛排煎的时间。因为一块牛排不管怎么分配到多少个锅里,时间是连续的。即
- 时间是可以无缝切换的资源池。考虑每个锅的平均的牛排时间消耗。即
确定了以后,考虑每个锅可分配的时间资源,顺序分配即可
solution
#include <bits/stdc++.h>
#define sc(x) scanf("%lld", &(x))
#define pr(x) printf("%lld\n", (x))
#define rep(i, t, r) for (int i = t; i <= r; ++i)
using namespace std;
typedef long long ll;
void pb(list<ll> &a, ll x, ll y, ll z) {
a.emplace_front(z), a.emplace_front(y), a.emplace_front(x);
}
signed main() {
int n, m;
scanf("%d%d", &n, &m);
vector<int> a(n);
ll sum = 0, ddl = 0;
for (int &x : a) scanf("%d", &x), ddl = max((ll)x, ddl), sum += x;
ddl = max(1LL * ddl, sum / m + (sum % m != 0));
vector<list<ll>> res(n);
int p = 0; // steak
rep(i, 1, m) {
ll tot = ddl, t = 0;
while (p < n and tot >= a[p]) {
pb(res[p], i, t, t += a[p]);
tot -= a[p++];
}
if (p == n) break;
if (tot) pb(res[p], i, t, ddl), a[p] -= ddl - t;
}
for (const list<ll> &v : res) {
printf("%d ", v.size() / 3);
for (const ll &x : v) printf("%lld ", x);
printf("\n");
}
return 0;
} I
题意
给定一些环形区间,要求构造一组区间,满足构造的区间的并是全集,且构造的区间的交是给定区间。
区间可能有重。
思路
首先把所有的区间合并。
然后按照如下方法构造区间:
简单来说,就是本区间的左端点和上一区间的右端点构成的优弧,形成了一个新的区间。
solution
双指针写法
#include <bits/stdc++.h>
#define sc(x) scanf("%lld", &(x))
#define pr(x) printf("%lld\n", (x))
#define rep(i, l, r) for (int i = l; i <= r; ++i)
using namespace std;
typedef long long ll;
const int N = 1e3 + 7;
const int mod = 1e9 + 7;
int a[N];
signed main() {
int T = 1, n, m, l, r;
struct intersection {
int L, R;
};
scanf("%d", &T);
while (T--) {
memset(a, 0, sizeof a);
scanf("%d%d", &n, &m);
while (m--) {
scanf("%d%d", &l, &r);
if (l > r) // [l,n] + [1,r]
a[l]++, a[n + 1]--, a[1]++, a[r + 1]--;
else // [l,r]
a[l]++, a[r + 1]--;
}
rep(i, 1, n) a[i] += a[i - 1];
vector<intersection> v;
int l = 1, r = 1;
while (r <= n) {
while (a[l] <= 0 && l <= n) ++l;
for (r = l + 1; r <= n && a[r] > 0; ++r)
;
--r;
if (l <= r && r <= n) {
v.push_back({l, r});
l = r + 1;
}
}
printf("%d\n", v.size());
for (int i = 0; i < v.size(); ++i)
printf("%d %d\n", v[i].L, v[(i - 1 + v.size()) % v.size()].R);
}
return 0;
} 简单写法
#include <bits/stdc++.h>
#define sc(x) scanf("%lld", &(x))
#define pr(x) printf("%lld\n", (x))
#define rep(i, l, r) for (int i = l; i <= r; ++i)
using namespace std;
typedef long long ll;
const int N = 1e3 + 7;
const int mod = 1e9 + 7;
int a[N];
signed main() {
int T = 1, n, m, l, r;
scanf("%d", &T);
while (T--) {
memset(a, 0, sizeof a);
scanf("%d%d", &n, &m);
while (m--) {
scanf("%d%d", &l, &r);
if (l > r) // [l,n] + [1,r]
a[l]++, a[n + 1]--, a[1]++, a[r + 1]--;
else // [l,r]
a[l]++, a[r + 1]--;
}
rep(i, 1, n) a[i] += a[i - 1];
vector<int> L, R;
rep(i, 1, n) {
if (a[i - 1] <= 0 and a[i] > 0) L.push_back(i);
if (a[i] > 0 and a[i + 1] <= 0) R.push_back(i);
}
printf("%d\n", L.size());
for (int i = 0; i < L.size(); ++i)
printf("%d %d\n", L[i], R[(i - 1 + R.size()) % R.size()]);
}
return 0;
} C
题意
给定一个n个点的完全图,每次删除一个完整的三角形,给出一种删法,让图的边数少于n
思路
因为每次删除的都是三角形,其实只用维护三角形,使后面出现的三角形和前面的三角形没有重复边即可。所以可以使用离散数学中群的知识来维护,维持三个点的递增性即可。
solution
#include <bits/stdc++.h>
#define sc(x) scanf("%lld", &(x))
#define pr(x) printf("%lld\n", (x))
#define rep(i, l, r) for (int i = l; i <= r; ++i)
using namespace std;
typedef long long ll;
const int N = 1e5 + 7;
const int mod = 1e9 + 7;
signed main() {
int n;
scanf("%d", &n);
printf("%d\n", n % 3 ? (n * n - 3 * n + 2) / 6 : (n * n - 3 * n + 6) / 6);
rep(i, 1, n) rep(j, i + 1, n) {
int k = (2 * n - i - j - 1) % n + 1;
if (k > j) printf("%d %d %d\n", i, j, k);
}
return 0;
} 
京公网安备 11010502036488号