/* 我们要找到在a,b左下方点的个数和权值和,只需要把x坐标不大于a的y值插入树状数组,然后统计y值小于b的个数个他们的权值和就行了。所以要得到正确答案,必须插入和查询同时进行(离线操作)——只有只插入x不大于a的y值的情况下统计出来才是正确答案。当然,由于y值范围大,值可能很稀疏,这样无疑会影响到插入和查询的时空效率。注意到,我们只关心比y小的个数和他们的权值,并不关心小多少之类的问题。所以把y按小到达映射成一个互异的升序数列可以很大得提高时空效率(离散化思想) 统计区间(a1,b1),(a2,b2)可以转换为统计 sum(b2,a2)-sum(a2,b1)-sum(a1,b2)+sum(a1,b1); 1 把所有的点以x升序排序p和qur数组 2 把所有y的坐标离散化 3 对于qur[i]把所有p[j].x小于qur[i].x的插入树状数组,并以qur[i].y统计 */ */ #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <set> #include<map> #include<ctime> using namespace std; const int MAXN = 180009; const int N = 180009; const int MAXV=60001; const double eps = 1e-6; struct point { int x,y; double val; int id; }p[MAXV],qur[2*MAXV]; bool cmp(point a,point b) { return a.x<b.x; } int anscnt[MAXN]; double anssum[MAXN]; double var[MAXN]; //*********************************************************** //树状数组 int ar[MAXN],n,q; int lowb(int t){return t&(-t);} void add(int i,int v,double val) { for(;i<N;ar[i]+=v,var[i]+=val,i+=lowb(i)); } void sum(int i,int &s,double &val) { s=0;val=0; for(;i>0;s+=ar[i],val+=var[i],i-=lowb(i)); } //*********************************************************** map<int,int> Map;//用做离散化y坐标 int main() { while(scanf("%d%d",&n,&q)!=EOF) { memset(ar,0,sizeof(ar)); memset(var,0,sizeof(var)); memset(anscnt,0,sizeof(anscnt)); memset(anssum,0,sizeof(anssum)); Map.clear(); for(int i=0;i<n;i++) { scanf("%d%d%lf",&p[i].x,&p[i].y,&p[i].val); Map[p[i].y]=1; } for(int i=0;i<4*q;i=i+4)//一次区间查询对应4次普通查询 { scanf("%d%d%d%d",&qur[i].x,&qur[i].y,&qur[i+3].x,&qur[i+3].y); qur[i].x--; qur[i].y--; qur[i].id=i; qur[i+1].id=i+1; qur[i+2].id=i+2; qur[i+3].id=i+3; qur[i+1].x=qur[i+3].x; qur[i+1].y=qur[i].y; qur[i+2].x=qur[i].x; qur[i+2].y=qur[i+3].y; Map[qur[i].y]=1; Map[qur[i+1].y]=1; Map[qur[i+2].y]=1; Map[qur[i+3].y]=1; } int k=0,g=0; for(map< int, int >::iterator it=Map.begin();it!=Map.end();it++) it->second=k++;//y的坐标值对应一个整数(从小到大) sort(p,p+n,cmp); sort(qur,qur+4*q,cmp); k=0,g=0; for(;;) { //cout<<p[k].y<<" "<<qur[g].y<<endl; if(k<n&&p[k].x<=qur[g].x) { add(Map[p[k].y],1,p[k].val); k++; } else { sum(Map[qur[g].y],anscnt[qur[g].id],anssum[qur[g].id]); g++;//cout<<"t"; } if(g>=4*q)break; } for(int i=0;i<4*q;i=i+4) printf("%.2lf/%d\n",anssum[i+3]-anssum[i+2]-anssum[i+1]+anssum[i]+eps,anscnt[i+3]-anscnt[i+2]-anscnt[i+1]+anscnt[i]);//避免-0.00,结果加上eps } return 0; }
HDU 3890 Apparent Magnitude 树状数组+离散化
最新推荐文章于 2020-10-20 17:01:30 发布