【BZOJ4311】向量(线段树分治,斜率优化)
【BZOJ4311】向量(线段树分治,斜率优化)
题面
题解
先考虑对于给定的向量集,如何求解和当前向量的最大内积。
设当前向量\((x,y)\),有两个不同的向量\((u1,v1),(u2,v2)\),并且\(u1>u2\)
假设第一个向量的结果优于第二个。
\(xu1+yv1>xu2+yv2\)
移项可以得到
\(x(u1-u2)>y(v2-v1)\)
所以\(x/y>(v2-v1)/(u1-u2)\)
也就是\(-x/y>(v1-v2)/(u1-u2)\)
右边是一个斜率,左边是询问向量和原点构成的斜率的垂线。
所以维护一个上凸壳,每次在上面二分(三分)一下就好了
时间复杂度\(O(nlog^2n)\)
按照之前听到的方法,因为每次询问如果排序之后,二分的结果是单调的,
所以暴力扫一遍就好。时间复杂度\(O(nlogn)\)
我写的是两个log的。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define lson (now<<1)
#define rson (now<<1|1)
#define MAX 200200
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
struct Vector{int x,y,l,r;}p[MAX],q[MAX];
bool cmp(Vector a,Vector b)
{
if(a.x!=b.x)return a.x<b.x;
return a.y<b.y;
}
int tot,Tim,n;
ll ans[MAX];
vector<Vector> seg[MAX<<2];
void Modify(int now,int l,int r,int L,int R,int id)
{
if(L<=l&&r<=R){seg[now].push_back(p[id]);return;}
int mid=(l+r)>>1;
if(L<=mid)Modify(lson,l,mid,L,R,id);
if(R>mid)Modify(rson,mid+1,r,L,R,id);
}
ll inner(Vector a,Vector b){return 1ll*a.x*b.x+1ll*a.y*b.y;}
ll Cross(Vector a,Vector b,Vector c){return 1ll*(a.x-c.x)*(b.y-c.y)-1ll*(a.y-c.y)*(b.x-c.x);}
Vector S[MAX];
int Top;
ll Query(int id)
{
int l=1,r=Top;ll ret=0;
while(l+3<=r)
{
int mid1=l+(r-l)/3,mid2=r-(r-l)/3;
if(inner(q[id],S[mid1])<=inner(q[id],S[mid2]))l=mid1;
else r=mid2;
}
for(int i=l;i<=r;++i)ret=max(ret,inner(q[id],S[i]));
return ret;
}
void Work(int now,int l,int r)
{
if(!seg[now].size())return;Top=0;
sort(seg[now].begin(),seg[now].end(),cmp);
for(int i=0,len=seg[now].size();i<len;++i)
{
Vector u=seg[now][i];
while(Top>1&&Cross(S[Top-1],S[Top],u)>=0)--Top;
S[++Top]=seg[now][i];
}
for(int i=l;i<=r;++i)ans[i]=max(ans[i],Query(i));
if(l==r)return;int mid=(l+r)>>1;
}
void Divide(int now,int l,int r)
{
Work(now,l,r);
if(l==r)return;int mid=(l+r)>>1;
Divide(lson,l,mid);Divide(rson,mid+1,r);
}
int main()
{
n=read();
for(int i=1;i<=n;++i)
{
int opt=read();
if(opt==1)
{
int x=read(),y=read();
p[++tot]=(Vector){x,y,Tim+1,-1};
}
else if(opt==2)
p[read()].r=Tim;
else
{
int x=read(),y=read();
q[++Tim]=(Vector){x,y,Tim,Tim};
}
}
for(int i=1;i<=tot;++i)if(p[i].r==-1)p[i].r=Tim;
for(int i=1;i<=tot;++i)if(p[i].l<=p[i].r)Modify(1,1,Tim,p[i].l,p[i].r,i);
Divide(1,1,Tim);
for(int i=1;i<=Tim;++i)printf("%lld\n",ans[i]);
return 0;
}
【BZOJ4311】向量(线段树分治,斜率优化)的更多相关文章
- bzoj4311向量(线段树分治+斜率优化)
第二道线段树分治. 首先设当前向量是(x,y),剩余有两个不同的向量(u1,v1)(u2,v2),假设u1>u2,则移项可得,若(u1,v1)优于(u2,v2),则-x/y>(v1-v2) ...
- 【BZOJ3672】【NOI2014】购票(线段树,斜率优化,动态规划)
[BZOJ3672][NOI2014]购票(线段树,斜率优化,动态规划) 题解 首先考虑\(dp\)的方程,设\(f[i]\)表示\(i\)的最优值 很明显的转移\(f[i]=min(f[j]+(de ...
- 【BZOJ-3672】购票 树分治 + 斜率优化DP
3672: [Noi2014]购票 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 1177 Solved: 562[Submit][Status][ ...
- 【BZOJ3672】[Noi2014]购票 树分治+斜率优化
[BZOJ3672][Noi2014]购票 Description 今年夏天,NOI在SZ市迎来了她30周岁的生日.来自全国 n 个城市的OIer们都会从各地出发,到SZ市参加这次盛会. ...
- [BZOJ4311]向量(凸包+三分+线段树分治)
可以发现答案一定在所有向量终点形成的上凸壳上,于是在上凸壳上三分即可. 对于删除操作,相当于每个向量有一个作用区间,线段树分治即可.$O(n\log^2 n)$ 同时可以发现,当询问按斜率排序后,每个 ...
- 2019.02.26 bzoj4311: 向量(线段树分治+凸包)
传送门 题意: 支持插入一个向量,删去某一个现有的向量,查询现有的所有向量与给出的一个向量的点积的最大值. 思路: 考虑线段树分治. 先对于每个向量处理出其有效时间放到线段树上面,然后考虑查询:对于两 ...
- BZOJ4311 向量(线段树分治+三分)
由点积的几何意义(即投影)可以发现答案一定在凸壳上,并且投影的变化是一个单峰函数,可以三分.现在需要处理的只有删除操作,线段树分治即可. #include<iostream> #inclu ...
- 洛谷.3733.[HAOI2017]八纵八横(线性基 线段树分治 bitset)
LOJ 洛谷 最基本的思路同BZOJ2115 Xor,将图中所有环的异或和插入线性基,求一下线性基中数的异或最大值. 用bitset优化一下,暴力的复杂度是\(O(\frac{qmL^2}{w})\) ...
- 线段树分治总结(线段树分治,线段树,并查集,树的dfn序,二分图染色)
闲话 stO猫锟学长,满脑子神仙DS 网上有不少Dalao把线段树分治也归入CDQ分治? 还是听听YCB巨佬的介绍: 狭义:只计算左边对右边的贡献. 广义:只计算外部对内部的贡献. 看来可以理解为广义 ...
随机推荐
- CentOS-6.4 minimal - 安装VMware Tools(linux)
本文参考自:http://www.cnblogs.com/xyq/p/4068018.html 1.挂载光驱 2./mnt下面默认显示以下文件 3.卸载/mnt 4.点击安装VMware Tools ...
- Android开发笔记——ListView模块、缓存及性能
ListView是Android开发中最常用的组件之一.本文将重点说明如何正确使用ListView,以及使用过程中可能遇到的问题. ListView开发模块 图片缓存 可能遇到的问题 一.ListVi ...
- 「日常训练」The Necklace(UVA-10054)
代码 for(int i=0; i!=n; ++i) { int u = cin.nextInt(); int v = cin.nextInt(); edges.add(new Edge(u,v)); ...
- .net mvc 使用ueditor的开发(官网没有net版本?)
1.ueditor的下载导入 官网下载地址:https://ueditor.baidu.com/website/download.html · 介绍 有两种,一种开发版,一种Mini版,分别长这样: ...
- Javascript深入__proto__和prototype的区别和联系
有一个一个装逼的同事,写了一段代码 function a(){} a.__proto__.__proto__.__proto__ 然后问我,下面这个玩意a.__proto__.__proto__.__ ...
- Alpha发布用户使用报告
此作业要求参见:[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2325] 组名:可以低头,但没必要 组长:付佳 组员:张俊余 李文涛 孙 ...
- lintcode-408-二进制求和
408-二进制求和 给定两个二进制字符串,返回他们的和(用二进制表示). 样例 a = 11 b = 1 返回 100 标签 二进制 字符串处理 脸书 思路 先相加,在处理进位,为了方便操作,将选字符 ...
- TCP系列45—拥塞控制—8、SACK关闭的拥塞撤销与虚假快速重传
一.概述 这篇文章介绍一下TCP从Recovery状态恢复到Open状态的时候cwnd的更新.我们在tcp重传部分的文章中曾经介绍过虚假重传的概念,Linux在探测到虚假重传的时候就会执行拥塞撤销操作 ...
- Java数学函数Math类
Java数学函数Math类常用: Math.abs(12.3); //12.3 返回这个数的绝对值 Math.abs(-12.3); //12.3 Math.copySign(1.23, -12.3) ...
- 成功解决JSP和Servlet的中文乱码问题
表单提交时出现乱码: 在进行表单提交的时候,经常提交一些中文,自然就避免不了出现中文乱码的情况,对于表单来说有两种提交方式:get和post提交方式.所以请求的时候便有get请求和post请求.以前我 ...