https://www.lydsy.com/JudgeOnline/problem.php?id=4311

你要维护一个向量集合,支持以下操作:
1.插入一个向量(x,y)
2.删除插入的第i个向量
3.查询当前集合与(x,y)点积的最大值是多少。如果当前是空集输出0

半个论文题吧……另外当空集的时候没有及时跳出结果WA了debug很难受。

参考:https://blog.csdn.net/outer_form/article/details/52277030

首先,每个向量都在第一象限,然后根据点积的基本定义,实际上就是给定向量与其他向量投影到给定向量的长度的乘积。

故在向量的无穷远处取一点,过这个点做垂线,然后将垂线往原点移,最先扫到的向量就是答案。

于是我们可以发现答案一定在点集的凸包上。

然而对于每个向量生效时间段不一样,所以我们把点排序后(这样建凸包的时候就不用再排序了)按时间建立线段树完后把点扔上去,然后对于每个区间的点集建立凸包跑一遍。

另外我们还可以发现把询问向量极角排序之后决策点单调(显然决策点是从凸包靠下的点慢慢变成靠上的点),于是跑一遍就可以了。

对于向量的极角排序正好用归并排序连同爬线段树一起做了,所以复杂度为O(nlogn)。

#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct point{
ll x,y;
point(){}
point(ll a,ll b){x=a,y=b;}
point operator-(const point &b)const{
return point(x-b.x,y-b.y);
}
}q[N],s[N];
struct data{
point a;
int l,r;
}p[N];
int n,pcnt,qcnt,tmp[N],t[N];
vector<point>tr[N*];
ll ans[N];
inline ll multiX(point a,point b){
return a.x*b.y-b.x*a.y;
}
inline ll multiP(point a,point b){
return a.x*b.x+a.y*b.y;
}
inline bool cmp(data a,data b){
point u=a.a,v=b.a;
return u.x>v.x||(u.x==v.x&&u.y>v.y);
}
void insert(int a,int l,int r,int l1,int r1,point x){
if(r<l1||r1<l)return;
if(l1<=l&&r<=r1){
tr[a].push_back(x);return;
}
int mid=(l+r)>>;
insert(a<<,l,mid,l1,r1,x);insert(a<<|,mid+,r,l1,r1,x);
}
void divide(int a,int l,int r){
if(l==r){
tmp[l]=l;
for(int i=;i<tr[a].size();i++)
ans[l]=max(ans[l],multiP(q[l],tr[a][i]));
return;
}
int mid=(l+r)>>;
divide(a<<,l,mid);divide(a<<|,mid+,r);
for(int i=l,j=l,k=mid+;i<=r;i++){
if(j<=mid&&(k>r||multiX(q[tmp[j]],q[tmp[k]])>=))t[i]=tmp[j++];
else t[i]=tmp[k++];
}
for(int i=l;i<=r;i++)tmp[i]=t[i];
int rr=;
for(int i=;i<tr[a].size();i++){
while(rr>&&multiX(tr[a][i]-s[rr-],s[rr]-s[rr-])>=)rr--;
s[++rr]=tr[a][i];
}
if(rr){
for(int i=l,j=;i<=r;i++){
while(j<rr&&multiP(q[tmp[i]],s[j+])>multiP(q[tmp[i]],s[j]))j++;
ans[tmp[i]]=max(ans[tmp[i]],multiP(q[tmp[i]],s[j]));
}
}
}
int main(){
n=read();
for(int i=;i<=n;i++){
int op=read();
if(op==){
int x=read(),y=read();
p[++pcnt].a=point(x,y);
p[pcnt].l=qcnt+;
p[pcnt].r=-;
}
if(op==){
int id=read();
p[id].r=qcnt;
}
if(op==){
int x=read(),y=read();
q[++qcnt]=point(x,y);
}
}
sort(p+,p+pcnt+,cmp);
for(int i=;i<=pcnt;i++){
if(p[i].r==-)p[i].r=qcnt;
if(p[i].l>p[i].r)continue;
insert(,,qcnt,p[i].l,p[i].r,p[i].a);
}
divide(,,qcnt);
for(int i=;i<=qcnt;i++)printf("%lld\n",ans[i]);
return ;
}

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

BZOJ4311:向量——题解的更多相关文章

  1. [BZOJ4311]向量(凸包+三分+线段树分治)

    可以发现答案一定在所有向量终点形成的上凸壳上,于是在上凸壳上三分即可. 对于删除操作,相当于每个向量有一个作用区间,线段树分治即可.$O(n\log^2 n)$ 同时可以发现,当询问按斜率排序后,每个 ...

  2. BZOJ4311 : 向量

    考虑离线操作,求出每个向量存在的时间区间,用时间线段树来进行分治,在每个节点求出凸壳后,询问时在凸壳上三分答案.时间复杂度$O(n\log^2n)$. #include<cstdio> # ...

  3. 2019.02.26 bzoj4311: 向量(线段树分治+凸包)

    传送门 题意: 支持插入一个向量,删去某一个现有的向量,查询现有的所有向量与给出的一个向量的点积的最大值. 思路: 考虑线段树分治. 先对于每个向量处理出其有效时间放到线段树上面,然后考虑查询:对于两 ...

  4. [BZOJ 2299][HAOI 2011]向量 题解(裴蜀定理)

    [BZOJ 2299][HAOI 2011]向量 Description 给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), ...

  5. BZOJ4311 向量(线段树分治+三分)

    由点积的几何意义(即投影)可以发现答案一定在凸壳上,并且投影的变化是一个单峰函数,可以三分.现在需要处理的只有删除操作,线段树分治即可. #include<iostream> #inclu ...

  6. bzoj4311向量(线段树分治+斜率优化)

    第二道线段树分治. 首先设当前向量是(x,y),剩余有两个不同的向量(u1,v1)(u2,v2),假设u1>u2,则移项可得,若(u1,v1)优于(u2,v2),则-x/y>(v1-v2) ...

  7. CCF-CSP认证 C++题解目录

    持续更新中,记录刷题过程并分享一下小小的心得总结. 试题编号 试题名称 标签 202006-1 线性分类器 | 题解 线性规划 202006-2 稀疏向量| 题解 归并排序思想 202006-3 化学 ...

  8. 【BZOJ4311】向量(线段树分治,斜率优化)

    [BZOJ4311]向量(线段树分治,斜率优化) 题面 BZOJ 题解 先考虑对于给定的向量集,如何求解和当前向量的最大内积. 设当前向量\((x,y)\),有两个不同的向量\((u1,v1),(u2 ...

  9. 【fake题解】[NOI2013]向量内积

    [fake题解][NOI2013]向量内积 做法1 大暴力.哪里不会T哪里. 做法2 所有数都%=k不影响结果.(废话 k的取值只有2和3,所以肯定是要分类讨论的.k=2肯定简单些啦. k=2 出现的 ...

随机推荐

  1. 怎样安装JMeter

    JMeter有图形界面, 而且支持中文! JMeter官网地址: http://jmeter.apache.org/ 点击左上角的下载: 点击下面的.zip后缀的压缩包: 解压到本地: JMeter目 ...

  2. 在本地电脑使用远程服务器的图形界面——包括 MATLAB、PyCharm 等各种软件

    在用本地电脑连接远程服务器的时候,大部分时候只能用命令行来操作.虽然可以 在本地电脑用 PyCharm 进行远程调试.在本地电脑远程使用服务器的 Jupyter Notebook.Ubuntu 和 W ...

  3. Solidity中的基本类型转换

    Solidity中的基本类型转换(十四)|入门系列 2017/4/29 posted in Solidity入门系列 点击查看原文,获得优化的排版. 隐式转换 如果一个运算符能支持不同类型.编译器会隐 ...

  4. 在JS中 实现不用中间变量temp 实现两个变量值得交换

    1.使用加减法; var a=1; var b=2; a=a+b; b=a-b; a=a-b; 2.使用乘除法(乘除法更像是加减法向乘除运算的映射) var a=1; var b=2; a = a * ...

  5. C中的除法,商和余数的大小、符号如何确定

    对于C中的除法,商和余数的大小.符号是如何确定的呢?在C89中,只规定了如果两个数为正整数,那么余数的符号为正,并且商的值是接近真实值的最大整数.比如5 / 2,那么商就是2,余数就是1.但是,C89 ...

  6. 常用web资源

    ip相关 新浪:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js&ip=220.181.38.110 (不带参数本机) ...

  7. Alpha阶段中间产物

    空天猎功能说明书:https://git.coding.net/liusx0303/Plane.git 空天猎代码控制:https://coding.net/u/MR__Chen/p/SkyHunte ...

  8. 新人学PHP,认为手动搭建环境而苦恼吗?这篇文章告诉你多简单!

    本教程适用于初学PHP,想了解手动搭建PHP环境的童鞋. 一键环境和高手勿喷. 本教程以下列版本软件为例: 所需软件目录 我在这里的目录结构是(个人习惯) 安装与配置 apache 双击安装Apach ...

  9. c# dllimport

    DllImport会按照顺序自动去寻找的地方:1.exe所在目录 2.System32目录 3.环境变量目录.所以只需要你把引用的DLL 拷贝到这三个目录下 就可以不用写路径了 或者可以这样serve ...

  10. 从电梯问题,看c和c++之间的区别(有点懂了)错觉错觉

    磕磕碰碰的也相继用c和c++构造了不少的电梯了.虽然对自我的表现不满意,但是总体来说还是有一定的收获的,对于c和c++之间的区别感觉也摸到了一点点门道了... 用c语言构造电梯的步骤: 第一步: 分析 ...