【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巨佬的介绍: 狭义:只计算左边对右边的贡献. 广义:只计算外部对内部的贡献. 看来可以理解为广义 ...
随机推荐
- 支付宝、微信、QQ 收款二维码三合一
最近折腾了一下合并收款码,简单记录一下折腾的过程,方法不唯一,只是提供一种思路,如果各位大佬有更加简单粗暴的办法,那就更好了. 原理 首先解析出三个二维码的内容,用 Nginx 判断 User age ...
- HCIE理论-IPV6
ipv4与ipv6的对比 IPv4 :32 bit 点分十进制 192.168.1.1 2^32=42.9亿 ipv4地址不足IPv6 :128 bit 十六进制 2^128 冒号分十六进制ipv4 ...
- Python异常(基础) except
为什么要异常处理机制:在程序调用层数较深时,向主调函数传递错误信息需要层层return 返回比较麻烦,用异常处理机制可以较简单的传送错误信息 什么是错误 错误是指由于逻辑或语法等导致一个程序已无法正常 ...
- JVM监控及堆栈内存
jconsole 堆内存:存放new出来的对象 栈内存:存放基本数据结构和对象的引用,但对象本身放在堆中
- Java:重写equals()和hashCode()
Java:重写equals()和hashCode() 1.何时需要重写equals() 当一个类有自己特有的“逻辑相等”概念(不同于对象身份的概念). 2.设计equals() [1]使用instan ...
- mongodb redis memcache 对比
从以下几个维度,对 Redis.memcache.MongoDB 做了对比. 1.性能 都比较高,性能对我们来说应该都不是瓶颈. 总体来讲,TPS 方面 redis 和 memcache 差不多,要大 ...
- RIGHT-BICEP测试第二次
1.Right-结果是否正确? 正确 2.B-是否所有的边界条件都是正确的? 正确 3.P-是否满足性能要求? 部分满足 4.是否满足有无括号? 无 5.数字个数是否不超过十? 只是双目运算 6.能否 ...
- C++:默认初始化
一.什么是默认初始化 默认初始化,顾名思义,即为在定义变量时如果没有为其指定初始化值,则该变量会被C++编译器赋予默认的值.而变量被赋予的默认值到底是什么,则取决于变量的数据类型和变量的定义位置. 二 ...
- 进击的SDN
SDN是什么? 不再是OSI七层模型,全新的SDN三层模型. 起源于斯坦福大学博士生领导的一个项目Ethane:通过一个集中式控制器(NOX),网络管理员可以定义基于网络流的控制策略,并将这个策略用于 ...
- [并查集] How Many Tables
题目描述 Today is Ignatius' birthday. He invites a lot of friends. Now it's dinner time. Ignatius wants ...