¶ D1 ( )
链接:https://codeforces.com/contest/1706/problem/D1
滑动窗口,每个
代码:
#include <cstdio>
#include <queue>
using namespace std;
constexpr int MAXN = 3011;
int main() {
int T;
static int a[MAXN];
static int p[MAXN];
("%d", &T);
scanfwhile (T--) {
int n, k;
("%d%d", &n, &k);
scanffor (int i = 1; i <= n; ++i) {
("%d", a + i);
scanf}
int ans = 0x3f3f3f3f;
int mn = 0x3f3f3f3f;
<pair<int, int> > pq;
priority_queuefor (int i = 1; i <= n; ++i) {
[i] = 1;
p}
for (int i = 1; i <= n; ++i) {
.push(make_pair(a[i], i));
pq= min(mn, a[i]);
mn }
while (1) {
int mx = pq.top().first;
int i = pq.top().second;
.pop();
pq= min(ans, mx - mn);
ans if (p[i] == k) {
break;
}
[i] += 1;
pint v = a[i] / p[i];
.push(make_pair(v, i));
pq= min(mn, v);
mn }
("%d\n", ans);
printf}
return 0;
}
¶ D1 ( )
注意到
代码:
#include <cstdio>
#include <queue>
using namespace std;
constexpr int MAXN = 3011;
int main() {
int T;
static int a[MAXN];
static int p[MAXN];
("%d", &T);
scanfwhile (T--) {
int n, k;
("%d%d", &n, &k);
scanffor (int i = 1; i <= n; ++i) {
("%d", a + i);
scanf}
int ans = 0x3f3f3f3f;
int mn = 0x3f3f3f3f;
<pair<int, int> > pq;
priority_queuefor (int i = 1; i <= n; ++i) {
[i] = 1;
p}
for (int i = 1; i <= n; ++i) {
.push(make_pair(a[i], i));
pq= min(mn, a[i]);
mn }
while (!pq.empty()) {
int mx = pq.top().first;
int i = pq.top().second;
.pop();
pq= min(ans, mx - mn);
ans if (mx == 0)
break;
[i] = a[i] / mx + 1;
pif (p[i] > k)
break;
int v = a[i] / p[i];
.push(make_pair(v, i));
pq= min(mn, v);
mn }
("%d\n", ans);
printf}
return 0;
}
¶ D2 ( )
D2的n和
注意到值域仅为1e5,因此可以采用类似桶排序的思路,搞一个数组
代码:
#include <cstdio>
#include <vector>
using namespace std;
constexpr int MAXN = 100011;
constexpr int MAXV = 100011;
int main() {
int T;
static int a[MAXN];
static int p[MAXN];
("%d", &T);
scanfwhile (T--) {
int n, k;
("%d%d", &n, &k);
scanffor (int i = 1; i <= n; ++i) {
("%d", a + i);
scanf}
int ans = 0x3f3f3f3f;
int mn = 0x3f3f3f3f;
<int> v[MAXV];
vectorfor (int i = 1; i <= n; ++i) {
[i] = 1;
p}
int mx = a[1];
for (int i = 1; i <= n; ++i) {
[a[i]].push_back(i);
v= min(mn, a[i]);
mn = max(mx, a[i]);
mx }
for (; mx; mx -= 1) {
if (v[mx].empty())
continue;
for (int i : v[mx]) {
= min(ans, mx - mn);
ans [i] = a[i] / mx + 1;
pif (p[i] > k)
goto out;
int val = a[i] / p[i];
[val].push_back(i);
v= min(mn, val);
mn }
[mx] = vector<int>();
v}
:
out("%d\n", ans);
printf}
return 0;
}
¶ D2 ( )
假设已知
要最大化
换句话说,假如
这里官方题解
这样,我们遍历
但是怎么求出这个最小值呢?注意到对每个
总的算法流程是枚举最大值
注意到
由于
遍历
因此总的复杂度为
代码:
#include <cstdio>
#include <vector>
using namespace std;
constexpr int MAXN = 100011;
constexpr int MAXV = 100011;
int main() {
int T;
static int a[MAXN];
static int ge[MAXV];
("%d", &T);
scanfwhile (T--) {
int n, k;
("%d%d", &n, &k);
scanf[0] = 0;
afor (int i = 1; i <= n; ++i) {
("%d", a + i);
scanf}
for (int i = n; i; --i) {
for (int j = a[i]; j > a[i-1]; --j) {
[j] = a[i];
ge}
}
[0] = a[1];
geint ans = 0x3f3f3f3f;
for (int v = a[n] / k; v <= a[n]; ++v) {
int mn = 0x3f3f3f3f;
for (int u = 1; u <= a[n] / (v + 1) + 1; ++u) {
int ai = ge[(u - 1) * (v + 1)];
if (ai < u * (v + 1)) {
= min(mn, ai / u);
mn }
}
= min(ans, v - mn);
ans }
("%d\n", ans);
printf}
return 0;
}