答案由$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. NYOJ题目1049自增自减

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAsYAAAN0CAIAAAA4f3koAAAgAElEQVR4nO3dO3LbyNoG4H8TyrUQx1

  2. haproxy 安装 各个参数的测试

    ---------------------------------------------------------------------------------------------------- ...

  3. OID View

    http://oid-info.com/get/1.3.6.1.2.1.17.1.4.1.2

  4. Asp.net窄屏页面 手机端新闻列表

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="SearchNotice.a ...

  5. Delphi之DLL知识学习4---创建DLL

    下面是在Delphi中创建一个DLL的全过程,你将看到怎样创建一个接口单元,使之可以被其他的应用程序访问.并且将学会怎么把Delphi的窗体加入DLL中. 一.数美分:一个简单的DLL 下面是包含一个 ...

  6. 突破python缺陷,实现几种自定义线程池 以及进程、线程、协程的介绍

    Python线程 Threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. #!/usr/bin/env python # -*- coding:utf-8 -*- import t ...

  7. revert merge会出现的问题

    比如当我们git revert的时候, git revert Git会抱怨: is a merge but no -m option was given 这是因为你revert的那个commit是一个 ...

  8. 攻城狮在路上(叁)Linux(二十八)--- 打包命令:tar

    首先介绍一下tar打包命令的基本格式,下面的三种之间不能混淆. tar [-j|-z] [cv] [-f 新文件名] file1 file2 ...; tar [-j|-z] [tv] [-f 新文件 ...

  9. 限制非安全IP访问

    这个是一个检测ip是否非法的php函数,适应于白名单,黑名单功能开发,主要场景应用于:api来源限制,访问限制等. /** * 安全IP检测,支持IP段检测 * @param string $ip 要 ...

  10. 解决linux下unzip中文有乱码的问题

    xxx.zip 中有中文的文件,在linux下unzip就会有乱码. 解决办法:安装7zip 去http://sourceforge.net/projects/p7zip/files/latest/d ...