题意:输入星星的坐标和亮度,查询不同矩形中星星的数目和亮度和
分析:用容斥原理的思想,拆点,按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; }