首页 > 代码库 > BZOJ 1935 SHOI2007 园丁的烦恼 树状数组

BZOJ 1935 SHOI2007 园丁的烦恼 树状数组

题目大意:给定平面上的一些点,多次询问某个矩形中有多少个点

将每个询问拆成4个 然后把所有询问和点都按照横坐标排序

对于每个询问,将所有x值小于等于这个询问的x的点的y值加入树状数组 然后在树状数组上查询小于等于这个询问的y值的点的数量

别被1000W吓到了 如果不爆内存的话1E也是能搞的 套个log就没多少了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 500500
using namespace std;
struct point{
	int x,y;
	void Read()
	{
		scanf("%d%d",&x,&y);
		++x;++y;
	}
	bool operator < (const point &Y) const
	{
		return x < Y.x ;
	}
}points[M];
struct query{
	int x,y,pos,flag;
	query(){}
	query(int _,int __,int ___,int ____):
		x(_),y(__),pos(___),flag(____){}
	bool operator < (const query &Y) const
	{
		return x < Y.x ;
	}
}queries[M<<2];
int n,m,ans[M];
int c[10001000];
void Update(int x)
{
	for(;x<=10000000;x+=x&-x)
		c[x]++;
}
int Get_Ans(int x)
{
	int re=0;
	for(;x;x-=x&-x)
		re+=c[x];
	return re;
}
int main()
{
	int i,j,x1,y1,x2,y2;
	cin>>n>>m;
	for(i=1;i<=n;i++)
		points[i].Read();
	sort(points+1,points+n+1);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		++x2;++y2;
		queries[i*4-3]=query(x1,y1,i,1);
		queries[i*4-2]=query(x1,y2,i,-1);
		queries[i*4-1]=query(x2,y1,i,-1);
		queries[i<<2 ]=query(x2,y2,i,1);
	}
	sort(queries+1,queries+m*4+1);
	for(i=1,j=1;i<=m<<2;i++)
	{
		for(;j<=n && points[j].x<=queries[i].x;j++)
			Update(points[j].y);
		ans[queries[i].pos]+=Get_Ans(queries[i].y)*queries[i].flag;
	}
	for(i=1;i<=m;i++)
		printf("%d\n",ans[i]);
}


BZOJ 1935 SHOI2007 园丁的烦恼 树状数组