答案由$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. 数据存储--sqlite总结

    SQLite SQLite(轻量级的数据库,关系型数据库) 辅助工具:Navicat Premium 等 原理:ios针对存储问题封装了sqlite数据库(c语言数据库). 1 app获取沙盒地址命名 ...

  2. selenium--python如何定位一组元素并返回文本值

    from selenium import webdriverimport time a=[] #创建一个空列表用于存储查询到的元素组driver = webdriver.Firefox()driver ...

  3. static_cast、dynamic_cast、reinterpret_cast、const_cast以及C强制类型转换的区别

    static_cast 1. 基础类型之间互转.如:float转成int.int转成unsigned int等 2. 指针与void*之间互转.如:float*转成void*.CBase*转成void ...

  4. 【Agorithm】一次一密加密解密算法

    #include<iostream> #include<cstdio> #include<cstdlib> #include<ctime> #inclu ...

  5. AOJ673 聪明的输入法(字典树)

    #include<cstdio> #include <cstdlib> #include <cstring> #include <iostream> # ...

  6. 攻城狮在路上(叁)Linux(二十七)--- 压缩与打包之常见的压缩命令

    前面讲到,linux中的后缀名没有特殊的意义,一般是作为不同文件类型的标识而已.下面是与打包.压缩相关的后缀名介绍: *.z:compress程序压缩文件 *.gz:gzip程序压缩文件 *.bz2: ...

  7. python解析RSS(feedparser)

    虽然说当今的博客已经不像前几年那么火了,但是RSS还是一项很有创造性和实用性的东西.RSS 是用于分发 Web 站点上的内容的摘要的一种简单的 XML 格式.它能够用于共享各种各样的信息.关于RSS的 ...

  8. 让用VS2012/VS2013编写的程序在XP中顺利运行

    转自:http://blog.csdn.net/asanscape/article/details/38752655/ 微软为了推销自家平台,默认配置下VS2012和VS2013编写的应用程序只能在V ...

  9. 19条ANDROID平台设计规范(转)

    1.尺寸以及分辨率: Android的界面尺寸比较流行的有:480*800.720*1280.1080*1920,我们在做设计图的 时候建议是以 480*800的尺寸为标准; 2.界面基本组成元素: ...

  10. cocoaPads 安装及出现Analyzing dependencies之后卡死解决方案

    1.安装 a. 查看源 gem sources -l b. 设置源: sudo gem sources -a http://ruby.taobao.org c. 删除源:sudo gem source ...