题目大意:
给定一个矩阵,矩阵内有
n
n
n棵树,给出
m
m
m个询问,每次询问一个矩形里有多少棵树。
n
,
m
<
=
5
∗
1
0
5
,
x
i
,
y
i
<
=
1
0
7
n,m<=5*10^5,x_i,y_i<=10^7
n,m<=5∗105,xi,yi<=107
本来以为要用
c
d
q
cdq
cdq分治,结果发现直接树状数组就珂以了……
把矩形中的树看成插入操作,就相当于在矩阵中
(
x
,
y
)
(x,y)
(x,y)的位置
+
1
+1
+1。
然后把每个询问拆成二维前缀和的形式,则每个询问就变成查询左下角为
(
1
,
1
)
(1,1)
(1,1)、右上角为
(
x
,
y
)
(x,y)
(x,y)的矩形内有多少棵树。
离线,把所有插入操作和查询操作以
x
x
x坐标为第一关键字,
y
y
y坐标为第二关键字排序,
那么若第
i
i
i个操作是询问操作,仅有
[
1
,
i
−
1
]
[1,i-1]
[1,i−1]中的查询操作能影响到它,因为第
i
i
i个操作后面的操作
x
x
x坐标都
>
=
x
i
>=x_i
>=xi(若
x
j
=
x
i
,
则
y
j
>
y
i
x_j=x_i,则y_j>y_i
xj=xi,则yj>yi)。
同理,若第
i
i
i个操作是查询操作,那么它不会影响到
[
1
,
i
−
1
]
[1,i-1]
[1,i−1]中的查询操作。
因此,对于每个询问操作,相当于求有多少个修改操作的
j
j
j满足
j
<
i
,
y
j
<
y
i
j<i,y_j<yi
j<i,yj<yi。
发现这是个单点修改,区间查询,就硬上树状数组就珂以了qwq
代码
#include<stdio.h>
#include<cstring>
#include<algorithm>
#include<math.h>
#include<vector>
#define re register int
#define rl register ll
#define lowbit(x) x&(-x)
using namespace std;
typedef long long ll;
int read() {
re x=0,f=1;
char ch=getchar();
while(ch<'0' || ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9') {
x=10*x+ch-'0';
ch=getchar();
}
return x*f;
}
inline void write(int x) {
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline char GetChar() {
char ch=getchar();
while(ch!='A' && ch!='B' && ch!='C') ch=getchar();
return ch;
}
namespace I_Love {
const int Size=500005;
int n,m,tot,maxn,ny[Size*5];
struct zyd {
int id,x,y,k,dt;
} Q[Size*5];
inline void Push(int x,int y,int k,int id) {
Q[++tot].x=x;
Q[tot].y=y;
Q[tot].k=k;
Q[tot].id=id;
Q[tot].dt=tot;
}
inline bool comp(zyd jzm,zyd xjp) {
if(jzm.x!=xjp.x) return jzm.x<xjp.x;
if(jzm.y!=xjp.y) return jzm.y<xjp.y;
return jzm.dt<xjp.dt;
}
int tree[Size];
inline void update(int x) {
for(re i=x; i<=maxn; i+=lowbit(i)) {
tree[i]++;
}
}
inline int query(int x) {
int ans=0;
for(re i=x; i; i-=lowbit(i)) {
ans+=tree[i];
}
return ans;
}
int out[Size];
void Fujibayashi_Ryou() {
n=read();
m=read();
for(re i=1; i<=n; i++) {
int x=read();
int y=read();
Push(x,y,0,0);
}
for(re i=1; i<=m; i++) {
int a=read();
int b=read();
int c=read();
int d=read();
Push(c,d,1,i);
Push(a-1,b-1,1,i);
Push(a-1,d,-1,i);
Push(c,b-1,-1,i);
}
sort(Q+1,Q+1+tot,comp);
for(re i=1; i<=tot; i++) {
ny[i]=Q[i].y;
}
sort(ny+1,ny+1+tot);
maxn=unique(ny+1,ny+1+tot)-(ny+1);
for(re i=1; i<=tot; i++) {
Q[i].y=lower_bound(ny+1,ny+1+maxn,Q[i].y)-ny;
}
for(re i=1; i<=tot; i++) {
if(!Q[i].k) {
update(Q[i].y);
} else if(Q[i].k==1) {
out[Q[i].id]+=query(Q[i].y);
} else {
out[Q[i].id]-=query(Q[i].y);
}
}
for(re i=1; i<=m; i++) {
printf("%d\n",out[i]);
}
}
}
int main() {
I_Love::Fujibayashi_Ryou();
return 0;
}