官方题解:http://pan.baidu.com/s/1sjQbY8H
洛阳城里春光好
题目大意:(其实出题人已经写的很简短了……直接copy的-_-。sorry!)
一个平面上的n个点构成一个点集。老师会进行Q次操作,每次操作有以下两种可能:
1. 插入操作:给定两个实数x,y,向点集中加入一个坐标为(x,y)的点。
2. 查询操作:给定实数k,取点集中任一点(x,y),求满足方程y=kx+b的b的最大值。
现在小Z想知道,对于数学老师的每次查询,符合题意的b值是多少。
容易发现我们要找的点是在 凸包上 上凸壳上!(一开始总在想凸包……我真是naive
然后凸包上的线段的斜率满足单调性,所以我们在凸包上二分(lower_bound)即可找到所求的点……
这题我是用两个map来实现的,一个map存凸包,另一个map存斜率。
这里我处理斜率的时候少考虑了一个地方:我在插入凸包中插入一个新点时(p[x]=y),是删除它左右两个点对应直线的斜率,再加入两个新的斜率,然后对凸包进行调整。然而如果p[x]这个位置原来就有一个点的话!就应该是删掉原来的点与两边的点之间线段的斜率,再加入新的斜率,然后对凸包进行调整。
比较开心的是get了一份平衡树维护凸包的模板~(来自这里:http://blog.csdn.net/auto_ac/article/details/10664641)
其实这个是上凸壳的……如果是凸包的话我们维护两个凸壳就好了,下凸壳的维护方法:将所有点的y坐标取反,然后维护一个新的“上凸壳”(对应原图的下凸壳)这两个凸壳只有第一个点和最后一个点会是相同的。
另外,这题用KD-Tree应该也可做。。。判一下四个角就可以了= =(思维难度和代码难度好像要更优一点,额……不过用map的话代码难度也没有很高
我写KDTree的Insert的时候没有把插进来的这个点赋值
1 //Round8 A 2 #include<vector> 3 #include<map> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<iostream> 8 #include<algorithm> 9 #define rep(i,n) for(int i=0;i<n;++i) 10 #define F(i,j,n) for(int i=j;i<=n;++i) 11 #define D(i,j,n) for(int i=j;i>=n;--i) 12 using namespace std; 13 typedef long long LL; 14 inline int getint(){ 15 int r=1,v=0; char ch=getchar(); 16 for(;!isdigit(ch);ch=getchar()) if (ch=='-') r=-1; 17 for(; isdigit(ch);ch=getchar()) v=v*10-'0'+ch; 18 return r*v; 19 } 20 const int N=1e5+10; 21 /*******************template********************/ 22 //#define debug 23 24 int n,m; 25 double ans=1; 26 typedef map<double,double> mii; 27 typedef map<double,double>::iterator iter; 28 #define X first 29 #define Y second 30 double cross(iter o,iter a,iter b){ 31 return (a->X - o->X) * (b->Y - o->Y) - 32 (a->Y - o->Y) * (b->X - o->X); 33 } 34 mii up,slop; 35 36 inline double slope(iter a,iter b){ 37 return (b->Y - a->Y)/(b->X - a->X); 38 } 39 bool inside(mii &p,double x,double y){ 40 if (!p.size()) return 0; 41 if (x<p.begin()->X || x>p.rbegin()->X) return 0; 42 if (p.count(x)) return y<=p[x]; 43 p[x]=y; 44 iter cur = p.lower_bound(x),i,j; 45 i=j=cur; i--; j++; 46 bool ret=cross(i,cur,j)>=0; 47 p.erase(cur); 48 return ret; 49 } 50 void add(mii &p,double x,double y){ 51 if (inside(p,x,y)) return; 52 if (p.count(x)){ 53 iter cur=p.lower_bound(x),i=cur,j=cur; 54 i--;j++; 55 if (cur!=p.begin()) slop.erase(slope(i,cur)); 56 if (j!=p.end()) slop.erase(slope(cur,j)); 57 } 58 p[x]=y; 59 iter cur=p.lower_bound(x),i=cur,j=cur; 60 i--; j++; 61 if (cur!=p.begin() && j!=p.end()) slop.erase(slope(i,j)); 62 if (cur!=p.begin()) slop[slope(i,cur)]=cur->X; 63 if (j!=p.end()) slop[slope(cur,j)]=j->X; 64 for(i=cur,i--,j=i,j--;i!=p.begin() && cur!=p.begin();i=j--) 65 if (cross(j,i,cur)>=0){ 66 slop.erase(slope(j,i)); 67 slop.erase(slope(i,cur)); 68 slop[slope(j,cur)]=cur->X; 69 p.erase(i); 70 } 71 else break; 72 for(i=cur,i++,j=i,j++;i!=p.end() && j!=p.end();i=j++) 73 if (cross(cur,i,j)>=0){ 74 slop.erase(slope(cur,i)); 75 slop.erase(slope(i,j)); 76 slop[slope(cur,j)]=j->X; 77 p.erase(i); 78 } 79 else break; 80 } 81 double query(double k){ 82 double x,y; 83 iter it=slop.lower_bound(k); 84 if (it==slop.end()) x=up.begin()->X,y=up.begin()->Y; 85 else x=it->Y,y=up[x]; 86 // printf("query k=%f tmpk=%f x=%f y=%f\n",k,it->X,x,y); 87 return y-k*x; 88 } 89 90 int main(){ 91 #ifndef ONLINE_JUDGE 92 freopen("A.in","r",stdin); 93 freopen("A.out","w",stdout); 94 #endif 95 int type=getint(); 96 double x,y,k; 97 n=getint(); m=getint(); 98 F(i,1,n){ 99 scanf("%lf%lf",&x,&y); 100 add(up,x,y); 101 #ifdef debug 102 // for(iter it=up.begin();it!=up.end();it++) 103 // printf("%f %f\n",it->X,it->Y); 104 // puts(""); 105 #endif 106 } 107 #ifdef debug 108 puts("up tu ke:"); 109 for(iter it=up.begin();it!=up.end();it++) 110 printf("%f %f\n",it->X,it->Y); 111 puts(""); 112 puts("xie lv & x :"); 113 for(iter it=slop.begin();it!=slop.end();it++) 114 printf("%f %f\n",it->X,it->Y); 115 puts(""); 116 #endif 117 char cmd[10]; 118 double ans=1; 119 F(i,1,m){ 120 scanf("%s",cmd); 121 if (cmd[0]=='i'){ 122 scanf("%lf%lf",&x,&y); 123 if (type==2) x=x/ans,y=y/ans; 124 add(up,x,y); 125 }else{ 126 scanf("%lf",&k); 127 if (type==2) k=k/ans; 128 printf("%.3f\n",ans=query(k)); 129 } 130 } 131 return 0; 132 }