隐藏
「bzoj2683」简单题 - CDQ分治三维偏序 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「bzoj2683」简单题 - CDQ分治三维偏序

题目大意

你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要维护两种操作:


题目分析

基本同Mokia
只是没有初始值而已。


代码

使用三维偏序普适框架:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const int maxn=500005,maxq=200005*4;
int n;
struct BIT {
int c[maxn];
#define lowbit(x) x&(-x)
void add(int x,int v) {
for(int i=x; i<=n; i+=lowbit(i))c[i]+=v;
}
void clear(int x,int v) {
for(int i=x; i<=n; i+=lowbit(i))c[i]=0;
}
int sum(int x) {
int sum=0;
for(int i=x; i>=1; i-=lowbit(i))sum+=c[i];
return sum;
}
} bit;
struct Point {
int x,y,v,id,time,opt;
Point() {}
Point(int _x,int _y,int _v,int _i,int _t,int _o):x(_x),y(_y),v(_v),id(_i),time(_t),opt(_o) {}
bool operator < (const Point& b) const {
return x<b.x||(x==b.x&&y<b.y)||(x==b.x&&y==b.y&&time<b.time);
}
} q[maxq],tmp[maxq];
int Ans[maxq];
void CDQBinary(int Left,int Right) {
if(Left==Right)return;
int mid=(Left+Right)>>1;
int lst=Left,rst=mid+1;
for(int i=Left; i<=Right; i++)
if(q[i].time<=mid)tmp[lst++]=q[i];
else tmp[rst++]=q[i];
for(int i=Left; i<=Right; i++)q[i]=tmp[i];
CDQBinary(Left,mid);
int j=Left;
for(int i=mid+1; i<=Right; i++) {
while(j<=mid&&q[j]<q[i]) {
if(q[j].opt==1)bit.add(q[j].y,q[j].v);
j++;
}
if(q[i].opt==2)Ans[q[i].id]+=q[i].v*bit.sum(q[i].y);
}
for(int i=Left; i<=mid; i++)
if(q[i].opt==1)bit.clear(q[i].y,0);
CDQBinary(mid+1,Right);
merge(q+Left,q+mid+1,q+mid+1,q+Right+1,tmp);
int tot=0;
for(int i=Left; i<=Right; i++)q[i]=tmp[tot++];
}
int m=0,opt[maxq],cnt=0;
int main() {
n=Get_Int();
while(true) {
opt[++m]=Get_Int();
if(opt[m]==1) {
int x=Get_Int(),y=Get_Int(),a=Get_Int();
q[++cnt]=Point(x,y,a,m,cnt,1);
} else if(opt[m]==2) {
int x1=Get_Int(),y1=Get_Int(),x2=Get_Int(),y2=Get_Int();
q[++cnt]=Point(x2,y2,1,m,cnt,2);
q[++cnt]=Point(x1-1,y2,-1,m,cnt,2);
q[++cnt]=Point(x2,y1-1,-1,m,cnt,2);
q[++cnt]=Point(x1-1,y1-1,1,m,cnt,2);
} else break;
}
sort(q+1,q+cnt+1);
CDQBinary(1,cnt);
for(int i=1; i<=m; i++)
if(opt[i]==2)printf("%d\n",Ans[i]);
return 0;
}

未使用三维偏序普适框架:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const int maxn=500005,maxq=200005*4;
int n;
struct BIT {
int c[maxn];
#define lowbit(x) x&(-x)
void add(int x,int v) {
for(int i=x; i<=n; i+=lowbit(i))c[i]+=v;
}
int sum(int x) {
int sum=0;
for(int i=x; i>=1; i-=lowbit(i))sum+=c[i];
return sum;
}
} bit;
struct Point {
int x,y,v,id,time,opt;
Point() {}
Point(int _x,int _y,int _v,int _i,int _t,int _o):x(_x),y(_y),v(_v),id(_i),time(_t),opt(_o) {}
bool operator < (const Point& b) const {
return x<b.x||(x==b.x&&y<b.y)||(x==b.x&&y==b.y&&time<b.time);
}
} q[maxq],tmp[maxq];
int Ans[maxq];
void CDQBinary(int Left,int Right) {
if(Left==Right)return;
int mid=(Left+Right)>>1;
for(int i=Left; i<=Right; i++)
if(q[i].time<=mid&&q[i].opt==1)bit.add(q[i].y,q[i].v);
else if(q[i].time>mid&&q[i].opt==2)Ans[q[i].id]+=q[i].v*bit.sum(q[i].y);
for(int i=Left; i<=Right; i++)
if(q[i].time<=mid&&q[i].opt==1)bit.add(q[i].y,-q[i].v);
int lst=Left,rst=mid+1;
for(int i=Left; i<=Right; i++)
if(q[i].time<=mid)tmp[lst++]=q[i];
else tmp[rst++]=q[i];
for(int i=Left; i<=Right; i++)q[i]=tmp[i];
CDQBinary(Left,mid);
CDQBinary(mid+1,Right);
}
int k,m=0,opt[maxq],cnt=0;
int main() {
n=Get_Int();
while(true) {
opt[++m]=Get_Int();
if(opt[m]==1) {
int x=Get_Int(),y=Get_Int(),a=Get_Int();
q[++cnt]=Point(x,y,a,m,cnt,1);
} else if(opt[m]==2) {
int x1=Get_Int(),y1=Get_Int(),x2=Get_Int(),y2=Get_Int();
q[++cnt]=Point(x2,y2,1,m,cnt,2);
q[++cnt]=Point(x1-1,y2,-1,m,cnt,2);
q[++cnt]=Point(x2,y1-1,-1,m,cnt,2);
q[++cnt]=Point(x1-1,y1-1,1,m,cnt,2);
} else break;
}
sort(q+1,q+cnt+1);
CDQBinary(1,cnt);
for(int i=1; i<=m; i++)
if(opt[i]==2)printf("%d\n",Ans[i]);
return 0;
}

姥爷们赏瓶冰阔落吧~