2022.10.19 总结
1. 逐月 P5076
题意
有 \(n\) 头奶牛,每头奶牛要么是 G,要么是 H。
当一张照片是连续的一段奶牛且里面的两种奶牛数量一样时,这张照片就是公平的照片,这张照片的大小是这张照片中奶牛的最大位置和最小位置的差。
请你求出最大的公平照片的大小是多少。
思路
100 分
把 G 看作 \(1\),H 看作 \(-1\)。
所以如果 \(i\) 到 \(j\) 是一张公平照片的话,会满足:
\(sum_j - sum_{i - 1} = 0\)
\(sum_j = sum_{i - 1}\)
所以可以记录下每一种和的最小下标,每次记录当前下标和之前的最小下标的差的最大值即可。
时间复杂度
每个奶牛只被枚举一次,\(O(n)\)。
空间复杂度
记录每只奶牛的坐标和品种,\(O(n)\)。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, ans, p[2 * N];
char c;
struct cow{
int x, b;
} a[N];
bool cmp(const cow &i, const cow &j){
return i.x < j.x;
}
int main(){
freopen("fairphoto.in", "r", stdin);
freopen("fairphoto.out", "w", stdout);
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> a[i].x >> c;
a[i].b = (c == 'G' ? 1 : -1);
}
sort(a + 1, a + n + 1, cmp);
for (int i = 1, j = 1; j <= n; i = j) { // 如果只有一只奶牛
for ( ; j <= n && a[i].b == a[j].b; j++) {
}
ans = max(ans, a[j - 1].x - a[i].x);
}
int s = n; // 偏移量
for (int i = 1; i <= n; i++) {
s += a[i].b;
if (p[s]) { // 如果有过
ans = max(ans, a[i].x - a[p[s] + 1].x);
} else { // 记录
p[s] = i;
}
}
cout << ans;
return 0;
}