P4390 [BOI2007]Mokia 摩基亚 题解
\(Description\)
\(Solution\)
CDQ分治板题
由于找一个矩形并不好处理,利用类似于二维前缀和的思想,把一个矩形拆成从 \((1, 1)\) 开始的 4 个矩形。
具体是哪 4 个从 \((1, 1)\) 开始的矩形自己手推一下吧,懒得打了。
考虑什么样的矩形对 \((x, y)\) 有贡献。
那么它需要满足三个条件:
- 在 \((x, y)\) 这个点之前出现。
- \(x_2 < x\)
- \(y_2 < y\)
于是这道题就变成了经典的三维偏序问题!
所以它就是个 \(CDQ\) 分治板子题。
注意这题的边界有点小问题,二维前缀和中我们要用到 \((x_1 - 1, y_1 - 1)\),但这可能是 0,所以输入时把所有坐标 +1 即可,包括 \(w\)。
\(Code\)
#include <bits/stdc++.h>
using namespace std;
namespace IO{
inline int read(){
int x = 0;
char ch = getchar();
while(!isdigit(ch)) ch = getchar();
while(isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
return x;
}
template <typename T> inline void write(T x){
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
}
using namespace IO;
const int N = 2e5 + 10;
const int M = 2e6 + 10;
struct node{
int op, id, x, y, val;
bool operator < (const node &b) const{
return x != b.x ? x < b.x : y < b.y;
}
}p[N];
int n, op, w;
namespace BIT{
int c[M];
inline void add(int x, int y){
for(; x <= w; x += x & (-x)) c[x] += y;
}
inline int qry(int x){
int res = 0;
for(; x; x -= x & (-x)) res += c[x];
return res;
}
}
using namespace BIT;
inline bool cmp(node a, node b){
return a.id < b.id;
}
inline void CDQ(int l, int r){
if(l == r) return;
int mid = (l + r) >> 1;
CDQ(l, mid), CDQ(mid + 1, r);
sort(p + l, p + mid + 1);
sort(p + mid + 1, p + r + 1);
int i = l, j = mid + 1;
while(j <= r){
while(p[i].x <= p[j].x && i <= mid){
if(!p[i].op) add(p[i].y, p[i].val);
++i;
}
if(p[j].op) p[j].val += qry(p[j].y);
++j;
}
for(j = l; j < i; ++j)
if(!p[j].op) add(p[j].y, -p[j].val);
}
int main(){
op = read(), w = read() + 1;
while(op != 3){
op = read();
if(op == 1){
int x = read() + 1, y = read() + 1, a = read();
p[++n] = (node){0, n, x, y, a};
}else if(op == 2){
int x1 = read(), y1 = read(), x2 = read() + 1, y2 = read() + 1;
p[++n] = (node){1, n, x1, y1, 0};
p[++n] = (node){1, n, x2, y2, 0};
p[++n] = (node){1, n, x2, y1, 0};
p[++n] = (node){1, n, x1, y2, 0};
}
}
CDQ(1, n);
sort(p + 1, p + 1 + n, cmp);
for(int i = 1; i <= n; ++i)
if(p[i].op) write(p[i].val + p[i + 1].val - p[i + 2].val - p[i + 3].val), puts(""), i += 3;
return 0;
}
\[\_EOF\_
\]