题解:P13826 [Ynoi Easy Round 2026] 寒蝉鸣泣之时
j23wuyifan · · 题解
Easy Round 还是比较善良的
题目相当于是矩形加,求有多少个点值为
首先这东西是无法直接做的,考虑将矩阵加离线下来做扫描线。那么有
看了其他题解后,我们可以转换思路,发现可以不对每个
设
到这里思路就讲完了,但是 Ynoi 的题是不会让你这么轻松的通过的。直接开
inline void rebuild(int x) {
if (mn[x] <= mx[x]) {
for (int i = L[x]; i <= R[x]; i ++) {
//-tag + m * t = v
//-tag = v - m * t
//m * r <= v - mn
//m * l >= v - mx
int v = a[i];
for (int j = max(1, (v - mx[x] + m - 1) / m); j <= min(k, (v - mn[x]) / m); j ++) {
ans[j] += sum[x][N + v - j * m];
}
}
for(int i = mn[x];i <= mx[x];i ++)sum[x][i + N] = 0;
mx[x] = -inf, mn[x] = inf;
}
}
inline void add(int l, int r, int x) {
if (pos[l] == pos[r]) {
rebuild(pos[l]);
for (int i = l; i <= r; i ++)a[i] += x;
} else {
rebuild(pos[l]);
rebuild(pos[r]);
for (int i = l; i <= R[pos[l]]; i ++)a[i] += x;
for (int i = pos[l] + 1; i <= pos[r] - 1; i ++)tag[i] += x;
for (int i = L[pos[r]]; i <= r; i ++)a[i] += x;
}
}
signed main() {
ios :: sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m;
block = sqrt(n);
tot = (n + block - 1) / block;
L[1] = 1, R[tot] = n;
for (int i = 2; i <= tot; i ++) L[i] = min(L[i - 1] + block, n);
for (int i = 1; i < tot; i ++) R[i] = L[i + 1] - 1;
for (int i = 1; i <= tot; i ++)for (int j = L[i]; j <= R[i]; j ++)pos[j] = i;
k = n / m;
for(int i = 1;i <= tot;i ++) mx[i] = -inf,mn[i] = inf;
for (int i = 1; i <= n; i ++) {
int a, b, c, d;
cin >> a >> b >> c >> d;
E[a].push_back({c, d - 1, 1});
E[b].push_back({c, d - 1, -1});
}
for (int i = 1; i <= n; i ++) {
for (auto p : E[i])add(p.l, p.r, p.x);
for (int j = 1; j <= tot; j ++)sum[j][N - tag[j]], mn[j] = min(mn[j], -tag[j]), mx[j] = max(mx[j], -tag[j]);
}
for(int i = 1;i <= tot;i ++)rebuild(i);
//最后记得处理
for(int i = 1;i <= k;i ++)cout << ans[i] << '\n';
return 0;
}