「Luogu P4390」Mokia
Posted hlw1
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「Luogu P4390」Mokia相关的知识,希望对你有一定的参考价值。
给出一个空的二维矩形( w 行 w 列)和一些操作,操作包括单点修改和查询子矩形内的数量和。 ((1 le w le 2000000))
分析
典型的三维偏序问题。
显然,要求 ((x_1,y1)(x_2,y_2)) 中的贡献,用一点点容斥,那么它就等于 ((1,1)(x_2,y_2)-(1,1)(x_1-1,y_2)-(1,1)(x_2,y_1-1)+(1,1)(x_1-1,y_1-1)) ,然后以时间为一维,我们就可以愉快地 CDQ 了。
当然,如果 y = 1 的话,我们将 y - 1 = 0 插入树状数组,会导致树状数组陷入死循环,所以我们将所有的坐标都 +1 ,同样的, w 也要 +1 。
代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 200005
#define M 2000003
#define lowbit(i) i&-i
#define tie0 cin.tie(0),cout.tie(0)
#define fastio ios::sync_with_stdio(false)
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
typedef long long ll;
template <typename T> inline void read(T &x) {
T f = 1; x = 0; char c;
for (c = getchar(); !isdigit(c); c = getchar()) if (c == '-') f = -1;
for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
x *= f;
}
struct ele { int x, y, tot, id, pa; } e[N];
int w, cnt, q;
int ans[N];
struct TreeArray {
int c[M];
void add(int i, int k) {
while (i <= w) {
c[i] += k;
i += lowbit(i);
}
}
int query(int i) {
int ret = 0;
while (i) {
ret += c[i];
i -= lowbit(i);
}
return ret;
}
} tr;
bool cmpid(ele a, ele b) { return a.id < b.id; }
bool cmpdt(ele a, ele b) { return a.x == b.x ? a.y < b.y : a.x < b.x; }
void CDQ(int l, int r) {
if (l == r) return;
int mid = l + r >> 1;
CDQ(l, mid), CDQ(mid + 1, r);
sort(e + l, e + 1 + mid, cmpdt), sort(e + 1 + mid, e + 1 + r, cmpdt);
int i, j;
for (i = l, j = mid + 1; j <= r; ++j) {
while (i <= mid && e[i].x <= e[j].x) {
if (!e[i].pa) tr.add(e[i].y, e[i].tot);
i++;
}
if (e[j].pa) e[j].tot += tr.query(e[j].y);
}
for (j = l; j < i; ++j) if (!e[j].pa) tr.add(e[j].y, -e[j].tot);
}
int main() {
//freopen("data.in", "r", stdin);
//freopen("my.out", "w", stdout);
int opt, x1, x2, y1, y2, k;
read(opt), read(w);
w++;
while (true) {
read(opt);
if (opt == 1) {
read(x1), read(y1), read(k);
e[++cnt] = (ele){++x1, ++y1, k, cnt, 0};
}
else if (opt == 2) {
read(x1), read(y1), read(x2), read(y2);
e[++cnt] = (ele){x1, y1, 0, cnt, 1};
e[++cnt] = (ele){++x2, ++y2, 0, cnt, 1};
e[++cnt] = (ele){x2, y1, 0, cnt, 1};
e[++cnt] = (ele){x1, y2, 0, cnt, 1};
}
else if (opt == 3) break;
}
//printf("cnt:%d
", cnt);
CDQ(1, cnt);
sort(e + 1, e + 1 + cnt, cmpid);
//for (int i = 1; i <= cnt; ++i)
//printf("id:%d x:%d y:%d tot:%d pa:%d
", e[i].id, e[i].x, e[i].y, e[i].tot, e[i].pa);
for (int i = 1; i <= cnt; ) {
if (e[i].pa) ans[++q] = e[i].tot + e[i+1].tot - e[i+2].tot - e[i+3].tot, i += 4;
else ++i;
}
for (int i = 1; i <= q; ++i) printf("%d
", ans[i]);
return 0;
}
以上是关于「Luogu P4390」Mokia的主要内容,如果未能解决你的问题,请参考以下文章