答案由$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题目170网络的可靠性

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAs8AAANvCAIAAACte6C6AAAgAElEQVR4nOydPbLcNhOu7yaUayGOZy

  2. tar 只解压tar包中某个文件

    sh-4.1# ls test.tar sh-4.1# tar -tf test.tar ./ecs20161207.png ./ecs.png ./ecs.xml ./rds.png ./Scree ...

  3. gzip

    gzip -c 将输出写到标准输出上,并保留原文本 gzip * : 把当前目录中的每个文件压缩成.gz文件 [root@NB gzip]# ls mysql-bin. mysql-bin..tar ...

  4. .net学习笔记---webconfig的读与写

    System.ConfigurationManager类用于对配置文件的读取.其具有的成员如下: 一.AppSettings AppSetting是最简单的配置节,读写非常简单. 名称 说明 AppS ...

  5. jQuery 操作复选框(checkbox) attr checked不起作用

    参考资料 http://www.paobuke.com/develop/javascript/pbk849.html   这天用到jQuery功能,想实现一个简单的复选框动态全选或全不选,结果测试发现 ...

  6. Pyqt 获取windows系统中已安装软件列表

    开始之前的基础知识 1. 获取软件列表 在Python的标准库中,_winreg可以操作Windows的注册表.获取已经安装的软件列表一般是读去windows的注册表: SOFTWARE\Micros ...

  7. 以16进制打印出一块内存buff

    如下代码(支持windows与Linux)会以[16进制][每行16字节]打印出一块内存的内容: void PrintBuffer(void* pBuff, unsigned int nLen) { ...

  8. [Nodejs]十分钟快速编写简单静态文件服务器

    学了几天Nodejs 后我又干上了前端的活.这次遇到的问题是,我想在不同的设备上方便的查看我编写的网页,很自然的就想到要是能在本地搭建一个简单的http服务器的话,那局域网内的所有设备都可以访问了,这 ...

  9. Tips for OpenMesh

    OpenMesh 求两点之间的距离 MyMesh::Point p1(1,2,3); MyMesh::Point p2(1,2,5); double d=(p1-p2).length();

  10. 直接拿来用!最火的Android开源项目(一) (转)

    对于开发者而言,了解当下比较流行的开源项目很是必要.利用这些项目,有时能够让你达到事半功倍的效果.为此,CSDN特整理了GitHub上最受欢迎的Android及iOS开源项目,本文详细介绍了20个An ...