BZOJ 1945 [Shoi2007]Tree 园丁的烦恼

starli posted @ 2016年2月02日 18:02 in 数据结构 , 329 阅读

离散化+树状数组统计 

看到这题第一个反应二维树状数组 看数据范围 这画风不对啊……

考虑离线解决这个问题

首先离散化y轴坐标

我们发现可以把一个询问拆成4个询问 一个是从(0,0)到(cj,dj)一个从(0,0)到(aj-1,bj-1)一个从(0,0)到(aj-1,dj)一个从(0,0)到(cj,bj-1),然后这个询问就可以用这几个相加减弄出来了。

将询问和树按横坐标排序后 从左往右扫一遍 遇到树就将其加入树状数组,遇到询问就查询一下,最后计算一下答案输出

#include <cstdio>
#include <algorithm>
using namespace std;
const int N=4000000;
struct query{int x,y,y0,op,id;}q[N+10];
struct tree{int x,y;}t[N+10];
int s[N+10],ans[N+10],n,m,cnt=0,tmp=0;
bool cmp(query a,query b){return a.x==b.x?a.op<b.op:a.x<b.x;}
bool cmp2(query a,query b){return a.y<b.y;}
bool cmp3(query a,query b){return a.id<b.id;}
void add(int x,int d){for(;x<=tmp;x+=x&-x) s[x]+=d;}
int sum(int x){int ret=0;for(;x;x-=x&-x) ret+=s[x];return ret;}
void read(int &x){char c;while((c=getchar())<'0' || c>'9');x=c-'0';while((c=getchar())>='0' && c<='9') x=x*10+c-'0';}
int main(){
	//freopen("1935.in","r",stdin);freopen("1935.out","w",stdout);
	// scanf("%d%d",&n,&m);
	read(n),read(m);q[0].y=-65478;
	for(int i=1;i<=n;i++) read(q[i].x),read(q[i].y);
	for(int i=1;i<=m;i++) {
		int x1,y1,x2,y2;
		read(x1);read(y1);read(x2);read(y2);
		// scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
		q[n+(++cnt)].x=x1-1;//q1;
		q[n+cnt].y=y1-1;
		q[n+cnt].id=cnt;
		q[n+cnt].op=1;
		q[n+(++cnt)].x=x1-1;//q2;
		q[n+cnt].y=y2;
		q[n+cnt].id=cnt;
		q[n+cnt].op=1;
		q[n+(++cnt)].x=x2;//q3;
		q[n+cnt].y=y1-1;
		q[n+cnt].id=cnt;
		q[n+cnt].op=1;
		q[n+(++cnt)].x=x2;//q4;
		q[n+cnt].y=y2;
		q[n+cnt].id=cnt;
		q[n+cnt].op=1;//ans[i]=q4-q2-q3+q1
	}
	sort(q+1,q+n+4*m+1,cmp2);
	for(int i=1;i<=n+4*m;i++) {if(q[i].y!=q[i-1].y) tmp++;q[i].y0=tmp;}
	sort(q+1,q+n+4*m+1,cmp);
	for(int i=1;i<=n+4*m;i++){
		if(!q[i].op) add(q[i].y0,1);
		else ans[q[i].id]=sum(q[i].y0);
	}
	for(int i=1;i<=m;i++) printf("%d\n",ans[4*i]-ans[4*i-1]-ans[4*i-2]+ans[4*i-3]);
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter