官方题解: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的时候没有把插进来的这个点赋值【ContestHunter】【弱省胡策】【Round8】【ContestHunter】【弱省胡策】【Round8】【ContestHunter】【弱省胡策】【Round8】

  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 }
View Code(map维护凸包)

相关文章: