Solution
发现坐标范围很大,考虑离散化
但离散之后还是不能用二维数据结构,数组大小太大
发现没有修改,只有查询
可以考虑 x 坐标依次增大时,只记录 y 坐标的信息
于是把询问分成四个以(0,0)为左下角的询问,依次算出再汇总
将 每个询问的坐标 和 树的坐标 放在一个数组中,离散化 y 坐标
按 x 坐标从小到大排序,x 坐标相等时树在前面,询问在后面
遍历数组,碰到树时树状数组中它的 y 坐标加 1
碰到询问时求树状数组中小于等于它的 y 坐标的和即可
Code
#include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; const int N=3e6+10; int tr[N],n,m,cnt,A,B,C,D,ans[N],tot; struct node { int x,id; bool operator <(const node &o)const { return x<o.x; } }a[N]; struct mode { int x,y,id,inv; bool operator <(const mode &o)const { return x==o.x?id<o.id:x<o.x; } }d[N]; int lowbit(int x) { return x&(-x); } int get(int x) { int ans=0; for(;x;x-=lowbit(x)) ans+=tr[x]; return ans; } void add(int x) { for(;x<=cnt;x+=lowbit(x)) tr[x]++; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { tot++; scanf("%d%d",&d[tot].x,&d[tot].y); d[tot].x++,d[tot].y++; d[tot].id=0; } for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&A,&B,&C,&D); A++,B++,C++,D++; d[++tot]=(mode){A-1,B-1,i,1}; d[++tot]=(mode){C,D,i,1}; d[++tot]=(mode){A-1,D,i,-1}; d[++tot]=(mode){C,B-1,i,-1}; } for(int i=1;i<=tot;i++) a[i].x=d[i].y,a[i].id=i; sort(a+1,a+1+tot); for(int i=1;i<=tot;i++) { if(i==1 || a[i].x!=a[i-1].x) cnt++; d[a[i].id].y=cnt; } sort(d+1,d+1+tot); for(int i=1;i<=tot;i++) { if(d[i].id) ans[d[i].id]+=d[i].inv*get(d[i].y); else add(d[i].y); } for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }