BZOJ 1176 Mokia
CDQ分治
求矩形面积可以看成类似二位前缀和的加减
这样就可以把题目看成x,y,t的三维偏序问题,直接上CDQ分治。
这里不用去重,但是我们在排序的时候一定要把三个维度相同的询问放在修改后面,因为CDQ每次分治都是计算左边对右边的贡献。
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
#define full(a, b) memset(a, b, sizeof a)
#define __fastIn ios::sync_with_stdio(false), cin.tie(0)
#define pb push_back
using namespace std;
using LL = long long;
inline int lowbit(int x){ return x & (-x); }
inline int read(){
int ret = 0, w = 0; char ch = 0;
while(!isdigit(ch)){
w |= ch == '-', ch = getchar();
}
while(isdigit(ch)){
ret = (ret << 3) + (ret << 1) + (ch ^ 48);
ch = getchar();
}
return w ? -ret : ret;
}
template <typename A>
inline A __lcm(A a, A b){ return a / __gcd(a, b) * b; }
template <typename A, typename B, typename C>
inline A fpow(A x, B p, C lyd){
A ans = 1;
for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
return ans;
}
const int N = 2000005;
int cur, opt, t, n, cnt, c[N], ans[N];
struct Query{
int op, id, x, y, t, val;
Query(){}
Query(int x, int y, int t, int val): x(x), y(y), t(t), val(val){
op = id = 0;
}
Query(int op, int id, int x, int y, int t, int val): op(op), id(id), x(x), y(y), t(t), val(val){}
bool operator < (const Query &rhs) const {
if(x != rhs.x) return x < rhs.x;
if(y != rhs.y) return y < rhs.y;
if(t != rhs.t) return t < rhs.t;
return val > rhs.val;
}
}v[N], aux[N];
inline void add(int k, int val){
for(; k <= t; k += lowbit(k)) c[k] += val;
}
inline int query(int k){
int ret = 0;
for(; k; k -= lowbit(k)) ret += c[k];
return ret;
}
void CDQ(int l, int r){
if(l == r) return;
int mid = (l + r) >> 1;
CDQ(l, mid), CDQ(mid + 1, r);
for(int i = l; i <= r; i ++){
aux[i - l] = v[i];
}
int i = 0, j = mid + 1 - l;
for(int k = l; k <= r; k ++){
if(i > mid - l){
if(aux[j].op != 0) ans[aux[j].id] += aux[j].op * query(aux[j].t);
v[k] = aux[j ++];
}
else if(j > r - l){
if(aux[i].op == 0) add(aux[i].t, aux[i].val);
v[k] = aux[i ++];
}
else if(aux[i].y <= aux[j].y){
if(aux[i].op == 0) add(aux[i].t, aux[i].val);
v[k] = aux[i ++];
}
else{
if(aux[j].op != 0) ans[aux[j].id] += aux[j].op * query(aux[j].t);
v[k] = aux[j ++];
}
}
for(int k = 0; k < mid - l + 1; k ++){
if(aux[k].op == 0) add(aux[k].t, -aux[k].val);
}
}
int main(){
for(;;){
opt = read();
if(opt == 3) break;
else if(opt == 0) n = read() + 1;
else if(opt == 1){
int x = read() + 1, y = read() + 1, w = read();
v[++cur] = Query(x, y, ++ t, w);
}
else{
int x1 = read() + 1, y1 = read() + 1, x2 = read() + 1, y2 = read() + 1;
cnt ++, t ++;
v[++cur] = Query(1, cnt, x2, y2, t, 0);
v[++cur] = Query(-1, cnt, x2, y1 - 1, t, 0);
v[++cur] = Query(-1, cnt, x1 - 1, y2, t, 0);
v[++cur] = Query(1, cnt, x1 - 1, y1 - 1, t, 0);
}
}
sort(v + 1, v + cur + 1);
CDQ(1, cur);
for(int i = 1; i <= cnt; i ++){
printf("%d\n", ans[i]);
}
return 0;
}