前言
相比于D1T1,这题才是真正的签到题,然而,我却爆0了。为了纪念这悲壮的0分,写下了这篇题解。
题目大意
给出 n ( 1 ≤ n ≤ 1 0 5 ) n(1\le n\le 10^5) n(1≤n≤105) 个字符串及其出现时间(以几点几分给出),每个字符串会存在 m ( 1 ≤ m ≤ 1440 ) m(1\le m\le 1440) m(1≤m≤1440) 个单位时间(分钟),求存在字符串最多的时间点有多少个字符串(注意:同个字符串在同一时间点重叠只算一个字符串)
解题思路
实际上,最麻烦的地方是相同会出现重叠,并且不管重叠几次,都只造成 1 1 1 的贡献。所以,显而易见,我们需要将每一个字符串分开考虑。参考下图:
由于重叠部分也只造成 1 1 1 的贡献,我们考虑进行区间合并。先按照左端点排序:
如果下一个区间的左端点小于这一个区间的右端点,那么一定可以进行区间合并,也就是将右端点后移,合并后,得到下图:
再进行区间加即可。相信大家第一个想到的都是差分,可是从这里开始,我突然脑抽了,果断打起了线段树,过了样例(因为太水了……),然后爆0了。赛后调出来了,写篇题解给自己一个警告:就算再喜欢线段树,考场上也尽量不要写!!!
代码实现
#include <bits/stdc++.h>
using namespace std;
struct node {long long l, r, laz, Max;
} segment_tre[10010];
struct node2 {long long f, t;
};
long long n, m, tot;
unordered_map<string, long long> mem;
vector<node2> v[100010], sorted_v[100010];
string s1, s2;
void setup(long long i, long long l, long long r) {segment_tre[i].l = l;segment_tre[i].r = r;if (l == r)return;long long mid = ((l + r) >> 1);setup(i * 2, l, mid);setup(i * 2 + 1, mid + 1, r);
}
void push_d(long long i) {if (segment_tre[i].laz != 0) {segment_tre[i * 2].Max += segment_tre[i].laz;segment_tre[i * 2].laz += segment_tre[i].laz;segment_tre[i * 2 + 1].Max += segment_tre[i].laz;segment_tre[i * 2 + 1].laz += segment_tre[i].laz;segment_tre[i].laz = 0;}return;
}
void change(long long i, long long l, long long r, long long num) {if (segment_tre[i].l >= l && segment_tre[i].r <= r) {segment_tre[i].laz++;segment_tre[i].Max++;return;}push_d(i);if (segment_tre[i * 2].r >= l)change(i * 2, l, r, num);if (segment_tre[i * 2 + 1].l <= r)change(i * 2 + 1, l, r, num);segment_tre[i].Max = max(segment_tre[i * 2].Max, segment_tre[i * 2 + 1].Max);return;
}
long long ask(long long i, long long l, long long r) {if (segment_tre[i].l >= l && segment_tre[i].r <= r)return segment_tre[i].Max;push_d(i);long long value = 0;if (segment_tre[i * 2].r >= l)value = max(value, ask(i * 2, l, r));if (segment_tre[i * 2 + 1].l <= r)value = max(value, ask(i * 2 + 1, l, r));return value;
}
long long work(string s) { return ((s[0] - '0') * 10 + s[1] - '0') * 60 + (s[3] - '0') * 10 + s[4] - '0'; }
int main() {ios::sync_with_stdio(false);cin.tie(0);freopen("switch.in", "r", stdin);freopen("switch.out", "w", stdout);cin >> n >> m;setup(1, 0, 24 * 60);for (int i = 1; i <= n; i++) {cin >> s1 >> s2;if (mem[s1] == 0) {mem[s1] = ++tot;v[tot].push_back((node2){ work(s2), work(s2) + m - 1 });} elsev[mem[s1]].push_back((node2){ work(s2), work(s2) + m - 1 });}for (int i = 1; i <= tot; i++) {sort(v[i].begin(), v[i].end(), [&](node2 q, node2 h) -> bool { return q.f < h.f; });long long f = v[i][0].f, t = v[i][0].t;for (int j = 1; j < v[i].size(); j++)if (v[i][j].f <= t)t = v[i][j].t;else {sorted_v[i].push_back((node2){ f, t });f = v[i][j].f;t = v[i][j].t;}sorted_v[i].push_back((node2){ f, t });}for (int i = 1; i <= tot; i++)for (int j = 0; j < sorted_v[i].size(); j++) change(1, sorted_v[i][j].f, sorted_v[i][j].t, 1);cout << ask(1, 0, 24 * 60);return 0;
}