[GDKOI2024 普及组] 读书 题解
题目描述
对于一个长度为
做法
显然,有零取零,有较小的取较小的。
通过上面这句话,我们可以发现,现在问题似乎转化成了求一段区间内的最小值。这是什么?
线段树!
我们可以用一颗线段树去维护一个区间内的最小值,记为
问题来了,如何判断无解呢?
读题可知,一本书最多只有
时间复杂度为
Code
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 5 * 1e05 + 7;
const int inf = 2147483647;
int n, d;
int a[MAXN];
int tree[MAXN * 4];
int g;
int cnt;
void Build(int l, int r, int p)
{
if(l == r)
{
tree[p] = a[l];
return ;
}
int mid = (l + r) >> 1 ;
Build(l, mid, p << 1);
Build(mid + 1, r, p << 1 | 1);
tree[p] = min(tree[p << 1], tree[p << 1 | 1]);
}
void Query(int p, int l, int r)
{
if(l == r)
{
tree[p] = inf, ++g;
return ;
}
int mid = (l + r) >> 1;
if(tree[p << 1] <= g) Query(p << 1, l, mid);
if(tree[p << 1 | 1] <= g) Query(p << 1 | 1, mid + 1, r);
tree[p] = min(tree[p << 1], tree[p << 1 | 1]);
return;
}
signed main()
{
// freopen("book.in", "r", stdin);
// freopen("book.out", "w", stdout);
scanf("%d%d", &d, &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
Build(1, n, 1);
int ans = 0;
for(;;)
{
ans++;
cnt++;
Query(1, 1, n);
if(tree[1] == inf) break;
if(cnt >= MAXN)
{
printf("-1");
return 0;
}
}
printf("%d", ans);
}