P2163 [SHOI2007]园丁的烦恼
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const int N=3e6+5; const int M=1e7+5; inline int read() { char c=getchar();int num=0; for(;!isdigit(c);c=getchar()); for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num; } struct QUE { int x,y,f,id; bool operator < (const QUE &A) const { return x==A.x?(y==A.y?id<A.id:y<A.y):x<A.x; } }tree[N]; int n,m,cnt; int bound; int bit[M]; inline void add(int x) { for(;x<=bound;x+=x&(-x)) ++bit[x]; } inline int query(int x) { int res=0; for(;x;x-=x&(-x)) res+=bit[x]; return res; } int ans[N]; int main() { n=read(),m=read(); for(int i=1;i<=n;++i) { tree[i].x=read(),++++tree[i].x, //树状数组下标不能从0开始,因为0的二进制上没有1,会死循环,所以让左标++ tree[i].y=read(),++++tree[i].y; bound=max(bound,tree[i].y); } cnt=n; for(int i=1,a,b,c,d;i<=m;++i) { a=read(),b=read(),c=read(),d=read(); ++a,++b,++++c,++++d; //a和b不用加,因为二维前缀和要-query(a+1-1)=query(a) tree[++cnt].x=a,tree[cnt].y=b,tree[cnt].f=1,tree[cnt].id=i; //二维前缀和 左上角 tree[++cnt].x=a,tree[cnt].y=d,tree[cnt].f=-1,tree[cnt].id=i; //左下角 tree[++cnt].x=c,tree[cnt].y=b,tree[cnt].f=-1,tree[cnt].id=i; //右上角 tree[++cnt].x=c,tree[cnt].y=d,tree[cnt].f=1,tree[cnt].id=i; //右下角 } sort(tree+1,tree+cnt+1); for(int i=1;i<=cnt;++i) { if(!tree[i].id) //插入 add(tree[i].y); else //查询 ans[tree[i].id]+=query(tree[i].y)*tree[i].f; } for(int i=1;i<=m;++i) printf("%d\n",ans[i]); return 0; }