题解:P12315 [蓝桥杯 2024 国 C] 挑苹果
tip:我附上了很多种语言的代码,这里我以我最擅长的C++来讲解。
则我们令:
则我们得到了满足条件的
特别地:如果区间跨越了模数边界(
事件统计
为了高效统计满足条件的
在区间
具体地,当遍历每个苹果的美味值
- 根据
t 和k ,计算满足条件的区间[l, r] :- 如果
l \le r ,发生两个事件:- 在
l 位置增加 1; - 在
r+1 位置减少 1。
- 在
- 如果
l \gt r (即区间跨越边界时),发生四个事件:- 在
l 位置增加 1; - 在
k 位置减少 1; - 在
0 位置增加 1; - 在
r + 1 位置减少 1。
- 在
- 如果
它的作用是通过统计事件,将区间操作转化为点操作,便于后续排序和扫描统计。
该部分代码:
vector<pair<int, int>> events;
for (int i = 0; i < n; ++i) {
int m = a[i] % k;
int l, r;
if (t >= k) {
l = 0;
r = k - 1;
} else {
l = (k - m) % k;
r = (l + t) % k;
if (l <= r) {
events.emplace_back(l, 1);
events.emplace_back(r + 1, -1);
} else {
events.emplace_back(l, 1);
events.emplace_back(k, -1);
events.emplace_back(0, 1);
events.emplace_back(r + 1, -1);
}
}
}
p.s:
在这里事件被存储在 events 数组中,每个事件是一个 pair<int, int>,其中:
first表示位置pos,即模k的余数范围的起点或终点。second表示变化量delta,可以是1(即表示开始增加)或-1(即表示开始减少)。
具体来说:
- 当
delta为1时,表示从这个位置开始,满足条件的苹果数量增加。 - 当
delta为-1时,表示从这个位置开始,满足条件的苹果数量减少。
事件排序与扫描部分
接下来,根据我们最开始提到的,我们要对数组进行排序。
事件排序
按照位置 pos 对事件排序,确保扫描时按顺序处理,这里直接使用 sort() 函数即可。
扫描统计
遍历事件,维护当前活跃区间的计数 current,并在每次位置变化时,更新最大值 max_count。
本部分代码
sort(events.begin(), events.end());
int max_count = 0;
int current = 0;
int prev_pos = 0;
for (const auto& event : events) {
int pos = event.first;
int delta = event.second;
if (pos > prev_pos) {
max_count = max(max_count, current);
}
current += delta;
prev_pos = pos;
}
max_count = max(max_count, current);
代码
最后献上我的代码:
C++:
#include <bits/stdc++.h>
using namespace std;
const int MAX_EVENTS = 200005; // 记得开2倍
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, k, t;
cin >> n >> k >> t;
int a[100005];
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
int diff[100005] = {0};
pair<int, int> events[MAX_EVENTS];
int event_count = 0;
for (int i = 0; i < n; ++i) {
int m = a[i] % k;
int l, r;
if (t >= k) {
l = 0;
r = k - 1;
} else {
l = (k - m) % k;
r = (l + t) % k;
if (l <= r) {
events[event_count++] = {l, 1};
events[event_count++] = {r + 1, -1};
} else {
events[event_count++] = {l, 1};
events[event_count++] = {k, -1};
events[event_count++] = {0, 1};
events[event_count++] = {r + 1, -1};
}
}
}
if (t >= k) {
cout << n << endl;
return 0;
}
sort(events, events + event_count);
int max_count = 0;
int current = 0;
int prev_pos = 0;
for (int i = 0; i < event_count; ++i) {
int pos = events[i].first;
int delta = events[i].second;
if (pos > prev_pos) {
max_count = max(max_count, current);
}
current += delta;
prev_pos = pos;
}
max_count = max(max_count, current);
cout << max_count << endl;
return 0;
}
C
using System;
using System.Collections.Generic;
class Program
{
const int MAX_EVENTS = 100005;
static void Main()
{
int n, k, t;
string[] input = Console.ReadLine().Split();
n = int.Parse(input[0]);
k = int.Parse(input[1]);
t = int.Parse(input[2]);
int[] a = new int[n];
input = Console.ReadLine().Split();
for (int i = 0; i < n; ++i)
{
a[i] = int.Parse(input[i]);
}
List<(int, int)> events = new List<(int, int)>();
for (int i = 0; i < n; ++i)
{
int m = a[i] % k;
int l, r;
if (t >= k)
{
l = 0;
r = k - 1;
}
else
{
l = (k - m) % k;
r = (l + t) % k;
if (l <= r)
{
events.Add((l, 1));
events.Add((r + 1, -1));
}
else
{
events.Add((l, 1));
events.Add((k, -1));
events.Add((0, 1));
events.Add((r + 1, -1));
}
}
}
if (t >= k)
{
Console.WriteLine(n);
return;
}
events.Sort((x, y) => x.Item1.CompareTo(y.Item1));
int maxCount = 0;
int current = 0;
int prevPos = 0;
foreach (var eventPair in events)
{
int pos = eventPair.Item1;
int delta = eventPair.Item2;
if (pos > prevPos)
{
maxCount = Math.Max(maxCount, current);
}
current += delta;
prevPos = pos;
}
maxCount = Math.Max(maxCount, current);
Console.WriteLine(maxCount);
}
}
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int k = scanner.nextInt();
int t = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
if (t >= k) {
System.out.println(n);
return;
}
List<Event> events = new ArrayList<>();
for (int i = 0; i < n; i++) {
int m = a[i] % k;
int l, r;
if (t >= k) {
l = 0;
r = k - 1;
} else {
l = (k - m) % k;
r = (l + t) % k;
if (l <= r) {
events.add(new Event(l, 1));
events.add(new Event(r + 1, -1));
} else {
events.add(new Event(l, 1));
events.add(new Event(k, -1));
events.add(new Event(0, 1));
events.add(new Event(r + 1, -1));
}
}
}
events.sort(Comparator.comparingInt(e -> e.pos));
int maxCount = 0;
int current = 0;
int prevPos = 0;
for (Event event : events) {
int pos = event.pos;
int delta = event.delta;
if (pos > prevPos) {
maxCount = Math.max(maxCount, current);
}
current += delta;
prevPos = pos;
}
maxCount = Math.max(maxCount, current);
System.out.println(maxCount);
}
static class Event {
int pos;
int delta;
Event(int pos, int delta) {
this.pos = pos;
this.delta = delta;
}
}
}
Python3
class Event:
def __init__(self, pos, delta):
self.pos = pos
self.delta = delta
def main():
n, k, t = map(int, input().split())
a = list(map(int, input().split()))
if t >= k:
print(n)
return
events = []
for i in range(n):
m = a[i] % k
if t >= k:
l, r = 0, k - 1
else:
l = (k - m) % k
r = (l + t) % k
if l <= r:
events.append(Event(l, 1))
events.append(Event(r + 1, -1))
else:
events.append(Event(l, 1))
events.append(Event(k, -1))
events.append(Event(0, 1))
events.append(Event(r + 1, -1))
events.sort(key=lambda e: e.pos)
max_count = 0
current = 0
prev_pos = 0
for event in events:
pos = event.pos
delta = event.delta
if pos > prev_pos:
max_count = max(max_count, current)
current += delta
prev_pos = pos
max_count = max(max_count, current)
print(max_count)
if __name__ == "__main__":
main()