答案由$3$部分构成:

$1$.抛物线的极值。

$2$.询问区间的左端点在抛物线上的值。

$3$.询问区间的右端点在抛物线上的值。

对于$1$,就是某个矩形范围内最大值查询,使用KD-Tree可以在$O(\sqrt{n})$的时间内完成询问。

对于$2$和$3$,对编号建线段树,每个节点维护该区间内最上方的轮廓线,那么每个节点的轮廓线可以由左右儿子的轮廓线通过归并得到。

归并时不断对两条抛物线求交点,在相邻关键点之间取较高的一段。

为了减小常数,可以在归并完成后将连续的所属同一条抛物线的轮廓线连起来。

查询时在线段树上找到$O(\log n)$个节点,然后在那些节点的轮廓线上二分查找即可。

总时间复杂度$O(n\log n+m(\log^2n+\sqrt{n}))$。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#define PB push_back
using namespace std;
const int N=50010;
const double eps=1e-6;
namespace KD{
int root,cmp_d,ans,X1,X2,Y1,Y2;
struct node{int d[2],l,r,Max[2],Min[2],val,sum;}t[N];
inline bool cmp(const node&a,const node&b){return a.d[cmp_d]<b.d[cmp_d];}
inline void umax(int&a,int b){if(a<b)a=b;}
inline void umin(int&a,int b){if(a>b)a=b;}
inline void up(int x){
if(t[x].l){
umax(t[x].Max[0],t[t[x].l].Max[0]);
umin(t[x].Min[0],t[t[x].l].Min[0]);
umax(t[x].Max[1],t[t[x].l].Max[1]);
umin(t[x].Min[1],t[t[x].l].Min[1]);
umax(t[x].sum,t[t[x].l].sum);
}
if(t[x].r){
umax(t[x].Max[0],t[t[x].r].Max[0]);
umin(t[x].Min[0],t[t[x].r].Min[0]);
umax(t[x].Max[1],t[t[x].r].Max[1]);
umin(t[x].Min[1],t[t[x].r].Min[1]);
umax(t[x].sum,t[t[x].r].sum);
}
}
int build(int l,int r,int D){
int mid=(l+r)>>1;
cmp_d=D;
nth_element(t+l+1,t+mid+1,t+r+1,cmp);
t[mid].Max[0]=t[mid].Min[0]=t[mid].d[0];
t[mid].Max[1]=t[mid].Min[1]=t[mid].d[1];
t[mid].sum=t[mid].val;
if(l!=mid)t[mid].l=build(l,mid-1,!D);
if(r!=mid)t[mid].r=build(mid+1,r,!D);
return up(mid),mid;
}
void ask(int x){
if(t[x].Min[0]>X2||t[x].Max[0]<X1||t[x].Min[1]>Y2||t[x].Max[1]<Y1||t[x].sum<=ans)return;
if(t[x].Min[0]>=X1&&t[x].Max[0]<=X2&&t[x].Min[1]>=Y1&&t[x].Max[1]<=Y2){
ans=t[x].sum;
return;
}
if(t[x].d[0]>=X1&&t[x].d[0]<=X2&&t[x].d[1]>=Y1&&t[x].d[1]<=Y2)umax(ans,t[x].val);
if(t[x].l)ask(t[x].l);
if(t[x].r)ask(t[x].r);
}
inline int query(int A,int B,int C,int D){
ans=0;
X1=A,X2=B,Y1=C,Y2=D;
ask(root);
return ans;
}
inline void init(int i,int x,int y){t[i].d[0]=i,t[i].d[1]=x,t[i].val=y;}
}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int n,m,i,A,B,C,D,a[N][3];double ans;
struct E{
double a,b,c;long long X,Y;
E(){}
E(double p,double x,double y,int _X,int _Y){
a=-y/(p-x)/(p-x);
b=-2*a*x;
c=y+a*x*x;
X=1LL*_X*_X,Y=_Y;
}
inline double f(double x){return a*x*x+b*x+c;}
}e[N];
inline double pos(const E&a,const E&b,double l,double r){
double A=a.a-b.a,B=a.b-b.b,C=a.c-b.c;
if(a.X*b.Y==a.Y*b.X){
if(fabs(B)<eps)return r;
double x=-C/B;
if(x>l+eps&&x<r)return x;
return r;
}
double d=B*B-4*A*C;
if(d<-eps)return r;
d=sqrt(d);
double x=(-B-d)/(2*A),y=(-B+d)/(2*A),ret=r;
if(x>l+eps&&x<r)ret=x;
if(y>l+eps&&y<r)ret=min(ret,y);
return ret;
}
struct P{
double l,r;int p;
P(){}
P(double _l,double _r,int _p){l=_l,r=_r,p=_p;}
};
vector<P>v[131100],c;
vector<double>q;
inline void merge(vector<P>&f,const vector<P>&a,const vector<P>&b){
int na=a.size(),nb=b.size(),i=0,j=0,k,top=0;
c.clear();
q.clear();
q.PB(-N);
while(i<na&&j<nb)if(a[i].r<b[j].r||j==nb){
if(a[i].r>q[top]+eps)q.PB(a[i].r),top++;
i++;
}else{
if(b[j].r>q[top]+eps)q.PB(b[j].r),top++;
j++;
}
for(;i<na;i++)if(a[i].r>q[top]+eps)q.PB(a[i].r),top++;
for(;j<nb;j++)if(b[j].r>q[top]+eps)q.PB(b[j].r),top++;
for(i=j=k=0;k<top;k++){
double l=q[k],r=q[k+1];
while(i<na&&a[i].r+eps<r)i++;
while(j<nb&&b[j].r+eps<r)j++;
if(i==na||a[i].l>l+eps){
c.PB(P(l,r,b[j].p));
continue;
}
if(j==nb||b[j].l>l+eps){c.PB(P(l,r,a[i].p));continue;}
if(!a[i].p||!b[j].p){c.PB(P(l,r,a[i].p+b[j].p));continue;}
double m,mid;
while(l+eps<r){
m=pos(e[a[i].p],e[b[j].p],l,r);
mid=(l+m)/2;
if(e[a[i].p].f(mid)>e[b[j].p].f(mid)){
c.PB(P(l,m,a[i].p));
}else{
c.PB(P(l,m,b[j].p));
}
l=m;
}
}
for(i=0,k=c.size();i<k;i=j){
for(j=i;j<k&&c[i].p==c[j].p;j++);
f.PB(P(c[i].l,c[j-1].r,c[i].p));
}
}
void build(int x,int a,int b){
if(a==b){
v[x].PB(P(-N,::a[a][0],0));
v[x].PB(P(::a[a][0],2*::a[a][1]-::a[a][0],a));
v[x].PB(P(2*::a[a][1]-::a[a][0],N,0));
return;
}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b);
merge(v[x],v[x<<1],v[x<<1|1]);
}
inline void query(const vector<P>&v,int o){
int l=0,mid,r=v.size()-1;
while(l<=r){
mid=(l+r)>>1;
if(v[mid].r+eps<o)l=mid+1;
else if(v[mid].l-eps>o)r=mid-1;
else{
ans=max(ans,e[v[mid].p].f(o));
return;
}
}
}
void ask(int x,int a,int b){
if(A<=a&&b<=B){
query(v[x],C);
query(v[x],D);
return;
}
int mid=(a+b)>>1;
if(A<=mid)ask(x<<1,a,mid);
if(B>mid)ask(x<<1|1,mid+1,b);
}
int main(){
read(n);
for(i=1;i<=n;i++){
int p,x,y;
read(p),read(x),read(y);
KD::init(i,x,y);
a[i][0]=p,a[i][1]=x,a[i][2]=y;
e[i]=E(p,x,y,p-x,y);
}
KD::root=KD::build(1,n,0);
build(1,1,n);
read(m);
while(m--){
read(A),read(B),read(C),read(D);
ans=KD::query(A,B,C,D);
ask(1,1,n);
printf("%.6f\n",ans);
}
return 0;
}

  

BZOJ2646 : neerc2011 flight的更多相关文章

  1. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  2. 2632: [neerc2011]Gcd guessing game

    2632: [neerc2011]Gcd guessing game Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 144  Solved: 84[S ...

  3. 使用QTP对Flight的登录界面进行测试

    一.测试用例设计 现在使用QTP对案例程序进行测试, 设计测试用例的要求为: 用户名长度大于等于6个字符 必须为字母[o-z,O-Z]和数字[0-9]组成 不能为空,空格或者特殊字符 正确的密码为:M ...

  4. 越狱Season 1- Episode 22: Flight

    Season 1, Episode 22: Flight -Franklin: You know you got a couple of foxes in your henhouse, right? ...

  5. 【BZOJ】【1020】【SHOI2008】安全的航线flight

    计算几何/二分/迭代/搜索+剪枝 写三个tag可能是因为从哪个方向来理解都可以吧…… 我完全不会计算几何所以抄了ydc的代码 题解:http://ydcydcy1.blog.163.com/blog/ ...

  6. nginx+php+flight 构建RESTFul API

    配置: Nginx: conf目录下nginx.conf配置文件. 第44行改为:root   D:/wwwroot/www; 第45行改为:index  index.html index.htm i ...

  7. 理解Flight框架核心

    http://blog.csdn.net/sky_zhe/article/details/38906689 Flight 框架 Flight类 1.加载 autoload.php ,启动框架的自动加载 ...

  8. Codeforces Gym 100531J Joy of Flight 变换坐标系

    Joy of Flight 题目连接: http://codeforces.com/gym/100531/attachments Description Jacob likes to play wit ...

  9. Codeforces_GYM Flight Boarding Optimization

    (ACM ICPC 2013–2014, NEERC, Northern Subregional Contest) Flight Boarding OptimizationInput file: fl ...

随机推荐

  1. iOS - UIButton设置图片文字上图下文排列

    经查阅资料及尝试,最终解决了在图片和文字垂直排列的情况下,如果文字长度变化会导致图片位置变动的问题,最开始采用了网上比较多的做法,做法如下: @interface UIButton (UIButton ...

  2. (转)ORA-12519: TNS:no appropriate service handler found 的问题处理。

    很多时候出现:ORA-12519: TNS:no appropriate service handler found 都是由于当前的连接数已经超出他能够处理的最大值了. 处理方法如下:摘自网上. se ...

  3. python检测文件的MD5值

    python检测文件的MD5值MD5(单向散列算法)的全称是Message-Digest Algorithm 5(信息-摘要算法),经MD2.MD3和MD4发展而来.MD5算法的使用不需要支付任何版权 ...

  4. x264中I,P,B帧和PTS,DTS的关系

    转自:http://www.cppblog.com/tx7do/archive/2013/01/30/197633.html 基本概念: I frame :帧内编码帧 又称intra picture, ...

  5. 如何在java程序中调用linux命令或者shell脚本

    转自:http://blog.sina.com.cn/s/blog_6433391301019bpn.html 在java程序中如何调用linux的命令?如何调用shell脚本呢? 这里不得不提到ja ...

  6. 第十篇:扩展SOUI的控件及绘图对象(ISkinObj)

    尽管SOUI已经内置了大部分常用的控件,很显然内置控件很难满足各种应用的形式各异的需求. 因此只有提供足够的扩展性才能满足真实应用场景. 除了将系统尽可能的组件化外,SOUI在控件自绘(SWindow ...

  7. 命令模式/command模式/行为型模式

    举个栗子 指挥官向士兵下达命令,士兵执行 实现代码如下: class Soldier { public void exe() { System.out.println("执行命令" ...

  8. 10个很棒的学习Android 开发的网站(转)

    看到江湖旅人 写的<10个很棒的学习iOS开发的网站 - 简书>,所以就忍不住写Android 啦,也希望对大家有帮助.我推荐的网站,都是我在学习Android 开发过程中发现的好网站,给 ...

  9. android之HttpURLConnection(转)

    android之HttpURLConnection 1.HttpURLConnection连接URL1)创建一个URL对象 URL url = new URL(http://www.baidu.com ...

  10. How to use Ajax on Visualforce page on Salesforce platform

    Just use Ajax pattern to call object data from server on visualforce page. Following is the Asynchro ...