3 条题解
-
1

#include<bits/stdc++.h> using namespace std; typedef long long LL; const int N = 2e5 + 10; const int M = 2 * N; int n, ln, cf, ans; // ln:离散化后点数, cf:当前覆盖 x 的区间数 int l1[N], r1[N], l2[N], r2[N]; // 输入的四元组 int dc[M]; // 离散化坐标(所有 l2 和 r2+1) LL sumb, mna, mxa, mnc, mxc, sumf; // 当前扫描到的累计值 LL bs[M], al[M], ar[M], cl[M], cr[M], f[M]; // 差分数组 // bs: 等于 x // al: amin // ar: amax // cl: cmin // cr: cmax // f: 覆盖x的区间数量的差分 (用于判断是否有区间包含x) void solve() { cin >> n; for (int i = 1; i <= ln; i ++) { bs[i] = al[i] = ar[i] = cl[i] = cr[i] = f[i] = 0; } ln = sumb = mna = mxa = mnc = mxc = sumf = ans = 0; for (int i = 1; i <= n; i ++) { cin >> l1[i] >> r1[i] >> l2[i] >> r2[i]; dc[++ ln] = l2[i]; dc[++ ln] = r2[i] + 1; // 我们将全闭区间变为左闭右开区间,方便计算差分 } sort(dc + 1, dc + 1 + ln); ln = unique(dc + 1, dc + 1 + ln) - dc - 1; // 构建差分数组,每个区间对四个量产生影响 for (int i = 1; i <= n; i ++) { // 这里的 x 和 y 对应着当前区间可选的最小值和最大值 int x = lower_bound(dc + 1, dc + 1 + ln, l2[i]) - dc; // 左端点位置 int y = lower_bound(dc + 1, dc + 1 + ln, r2[i] + 1) - dc; // 右端点 + 1 位置 // 等于当前值的区间贡献:在 [l2, r2] 内增加 r1 bs[x] += r1[i]; bs[y] -= r1[i]; // 当前值区间作为别人的 a al[y] += l1[i]; // 当别人的 amin,取最少的数量 ar[y] += r1[i]; // 当别人的 amax,取最多的数量 // 当前值区间作为别人的 c cl[1] += l1[i]; // 当别人的 cmin,取最少的数量 cl[x] -= l1[i]; // 只有比 x 小的才能选为 c cr[1] += r1[i]; // 当别人的 cmax,取最多的数量 cr[x] -= r1[i]; // 只有比 x 小的才能选为 c // 覆盖当前值的区间数量计数 f[x] ++; f[y] --; } for (int i = 1; i < ln; i ++) { // 累计当前点的值 sumb += bs[i]; // 等于 x 的个数总和 mna += al[i]; // 小于 x 的最小可能个数 mxa += ar[i]; // 小于 x 的最大可能个数 mnc += cl[i]; // 大于 x 的最小可能个数 mxc += cr[i]; // 大于 x 的最大可能个数 sumf += f[i]; // 覆盖 x 的区间数量 // 必须有区间覆盖 x(否则 x 不会出现在集合中) if (sumf == 0) continue; LL lef = max(mna - sumb + 1, mnc); LL rig = min(mxa + sumb, mxc); if (lef <= rig) { // 这段区间内所有整数点都满足条件,加入长度 ans += dc[i + 1] - dc[i]; } } cout << ans << "\n"; } int main () { ios::sync_with_stdio(false); cin.tie(0); int c, T; cin >> c >> T; while(T --) { solve(); } return 0; }
信息
- ID
- 2344
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 8
- 标签
- 递交数
- 33
- 已通过
- 7
- 上传者