hdu3890Apparent Magnitude 输入星星的坐标,查询不同矩形中星星的数目和亮度和

        题意:输入星星的坐标和亮度,查询不同矩形中星星的数目和亮度和

        分析:用容斥原理的思想,拆点,按x排序,y建数状数组,查询。

//树状数组
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;

struct point
{
	int x,y,flag,tag;//flag标记是查寻哪个矩阵。如果只是加点则是0
	double c;//tag表示容斥原理是加还是减。加为1,减为-1
}p[141000];
struct tree
{
	double c;
	int num;
}T1[141000],T2[21000];
int x[141000],y[141000],xnum,ynum;

bool cmp(point a,point b)//所有的点先按x,再按y,再按矩阵号(因为x,y相等时,肯定要先加点,后查询矩阵)
{
	if(a.x!=b.x) return a.x<b.x;
	if(a.y!=b.y) return a.y<b.y;
	return a.flag<b.flag;
}
void Add(int index,int x,int y,int flag,int tag)//加一点
{
	p[index].x=x,p[index].y=y;
	p[index].flag=flag,p[index].tag=tag;
}

int Lowbit(int t)
{
	return t^(t&(t-1));
}
void AddNum(int index,double c)//按y建树状数组,下标为1至ynum
{
	int i;
	for(i=index;i<=ynum;i+=Lowbit(i))
	{
		T1[i].num++;
		T1[i].c+=c;
	}
}
void Query(int index,int now)//查询,用树状数组的值更新矩阵的值
{
	int i;
	for(i=index;i>0;i-=Lowbit(i))
	{
		T2[p[now].flag].c=T2[p[now].flag].c+T1[i].c*p[now].tag;
		T2[p[now].flag].num=T2[p[now].flag].num+T1[i].num*p[now].tag;
	}
}
int BiSearch(int now)//在y中二分查找,返回第一个大于now的下标
{
	int l=0,r=ynum-1,mid;
	while(l<=r)
	{
		mid=(l+r)/2;
		if(y[mid]>now) r=mid-1;
		else l=mid+1;
	}
	return l;
}
int main()
{
	int n,m,i,j,x1,y1,x2,y2;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		for(xnum=0,ynum=0,i=0;i<n;i++)
		{
			scanf("%d%d%lf",&p[i].x,&p[i].y,&p[i].c);
			p[i].flag=0;
			x[xnum++]=p[i].x;
			y[ynum++]=p[i].y;
		}
		for(i=0;i<m;i++)
		{
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			x[xnum++]=x2,x[xnum++]=x1-1;
			y[ynum++]=y2,y[ynum++]=y1-1;

			//根据容斥原理加四点
			Add(n+4*i,x1-1,y1-1,i+1,1);
			Add(n+4*i+1,x1-1,y2,i+1,-1);
			Add(n+4*i+2,x2,y1-1,i+1,-1);
			Add(n+4*i+3,x2,y2,i+1,1);
			T2[i+1].num=0;
			T2[i+1].c=0;
		}
		sort(x,x+xnum);//排序去重
		sort(y,y+ynum);
		for(j=1,i=1;i<xnum;i++)
			if(x[i]!=x[i-1])
				x[j++]=x[i];
		xnum=j;

		for(j=1,i=1;i<ynum;i++)
			if(y[i]!=y[i-1])
				y[j++]=y[i];
		ynum=j;

		for(i=0;i<=ynum+1;i++)
		{
			T1[i].c=0;
			T1[i].num=0;
		}

		sort(p,p+n+4*m,cmp);
		//x已经排序,查y
		for(y1=0,i=0;i<n+4*m;i++)
		{
			if(!p[i].flag)//加一点
			{
				y1=BiSearch(p[i].y);
				//返回的是大于,更新时,自己也要算进去而更新时树状数组的下标是从1到ynum
				AddNum(y1,p[i].c);
			}
			else
			{
				y1=BiSearch(p[i].y);
				Query(y1,i);
			}
		}
		for(i=1;i<=m;i++)
		{
			if(!T2[i].num)
				printf("0.00/0\n");
			else
				printf("%.2lf/%d\n",T2[i].c,T2[i].num);
		}
	}
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值