SDOI 2014 向量集
[SDOI2014]向量集
题目描述
输入输出格式
输入格式
输出格式
输入输出样例
输入样例 #1
6 A
A 3 2
Q 1 5 1 1
A 15 14
A 12 9
Q 12 8 12 15
Q 21 18 19 18
输出样例 #1
13
17
17
说明
[题意]
维护向量序列,支持在序列末尾添加向量,以及询问某个区间中的向量与给定向量的点积的最大值。
[官方题解]

[个人题解](网上东拼西凑的)
一般性设当前询问的$y_0>0$,那么$\dfrac{ans}{y_0}=\max\{\dfrac{x_0}{y_0}\cdot x+y\}$,然后这个东西和斜率优化长得一样,答案一定是在凸壳上的.
于是我们维护这个凸壳.因为有区间询问所以线段树维护每个区间的凸壳.具体地,插入的时候统计当前区间已经有多少个点,如果点数等于当前区间长度那么构造出这个区间的凸壳.询问的时候拆成$\log$个区间分别跑二分/三分即可.
求凸包这里使用按$x$坐标排序的那个算法.注意如果几个点的$x$相同那么要按$y$排序.
插入的时候每个区间只会被构建一次凸包,总复杂度$O(n\log n)$,排序用归并.
查询的时候拆成$\log$个区间,每个区间$O(\log n)$三分/二分,总复杂度$O(n\log ^2 n)$
每个区间都要构建一次凸包,可以这么处理:每个线段树节点放个指针,动态开辟空间建立凸包。
网上不少代码把情况讨论合并成一种,只维护上凸壳。保险起见,也为了自己能够更好地理解,我还是分类讨论,同时维护上下凸壳。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
register char ch=getchar();x=;register bool f=;
for(;ch<''||ch>'';ch=getchar()) if(ch=='-') f=;
for(;ch>=''&&ch<='';ch=getchar()) x=x*+ch-'';
if(f) x=-x;
}
const int N=4e5+;
int n,m,cnt;ll ans;char type[],op[];
struct Q{
int opt,l,r,x,y;
Q(){}
Q(int opt,int l,int r,int x,int y):opt(opt),l(l),r(r),x(x),y(y){}
}q[N];
struct point{
int x,y;
point(int x=,int y=):x(x),y(y){}
point operator +(const point &a)const{
return point(x+a.x,y+a.y);
}
point operator -(const point &a)const{
return point(x-a.x,y-a.y);
}
ll operator *(const point &a)const{
return (ll)x*a.x+(ll)y*a.y;
}
ll operator ^(const point &a){
return (ll)x*a.y-(ll)y*a.x;
}
bool operator <(const point &a)const{
return x==a.x?y<a.y:x<a.x;
}
}p[N],tmp[N];int tmpsize;
struct CH{
point *up,*dw;
int upsize,dwsize;
void init(int l,int r){
up=new point[r-l+];
dw=new point[r-l+];
tmpsize=upsize=dwsize=;
for(int i=l;i<=r;i++) tmp[++tmpsize]=p[i];
sort(tmp+,tmp+tmpsize+);
for(int i=;i<=tmpsize;i++){
for(;upsize>&&((tmp[i]-up[upsize])^(up[upsize]-up[upsize-]))<=;upsize--);
up[++upsize]=tmp[i];
for(;dwsize>&&((dw[dwsize]-dw[dwsize-])^(tmp[i]-dw[dwsize]))<=;dwsize--);
dw[++dwsize]=tmp[i];
}
}
ll qmax(point p){
int l,r,mid1,mid2;ll res=-(1LL<<);
if(p.y>=){
l=;r=upsize;
while(r-l>){
mid1=l+(r-l)/;
mid2=r-(r-l)/;
if(up[mid1]*p<up[mid2]*p)
l=mid1;
else
r=mid2;
}
for(int i=l;i<=r;i++) res=max(res,up[i]*p);
}
else{
l=;r=dwsize;
while(r-l>){
mid1=l+(r-l)/;
mid2=r-(r-l)/;
if(dw[mid1]*p<dw[mid2]*p)
l=mid1;
else
r=mid2;
}
for(int i=l;i<=r;i++) res=max(res,dw[i]*p);
}
return res;
}
}b[N<<];bool tag[N<<];
#define lch k<<1
#define rch k<<1|1
ll query(int k,int l,int r,int x,int y,point p){
if(l==x&&r==y){
if(!tag[k]) tag[k]=,b[k].init(l,r);
return b[k].qmax(p);
}
int mid=l+r>>;
if(y<=mid) return query(lch,l,mid,x,y,p);
else if(x>mid) return query(rch,mid+,r,x,y,p);
else return max(query(lch,l,mid,x,mid,p),query(rch,mid+,r,mid+,y,p));
}
inline void decode(int &x){
if(type[]=='E') return ;
x=x^(ans&0x7fffffff);
}
int main(){
read(m);scanf("%s",type);
for(int i=,opt,x,y,l,r;i<=m;i++){
scanf("%s",op);opt=(op[]=='Q');
if(opt){
read(x);read(y);
read(l);read(r);
}
else{
read(x);read(y);l=r=;
++n;
}
q[i]=Q(opt,l,r,x,y);
}
for(int i=,l,r,x,y;i<=m;i++){
if(q[i].opt){
l=q[i].l;r=q[i].r;
x=q[i].x;y=q[i].y;
decode(l);decode(r);
decode(x);decode(y);
ans=query(,,n,l,r,point(x,y));
printf("%lld\n",ans);
}
else{
x=q[i].x;y=q[i].y;
decode(x);decode(y);
p[++cnt]=point(x,y);
}
}
return ;
}
收获:
所有形如$f[i]=\min\limits_{L(i)\leq j\leq R(i)}\{k(i)x(j)+F(j)\}+G(i)$的$dp$都是可做的(斜率优化型动态规划)
SDOI 2014 向量集的更多相关文章
- BZOJ 3533 sdoi 2014 向量集
设(x,y)为Q的查询点,分类讨论如下:1.y>0: 最大化a*x+b*y,维护一个上凸壳三分即可 2.y<0:最大化a*x+b*y 维护一个下凸壳三分即可 我们考虑对时间建出一棵线段 ...
- BZOJ 3533: [Sdoi2014]向量集( 线段树 + 三分 )
答案一定是在凸壳上的(y>0上凸壳, y<0下凸壳). 线段树维护, 至多N次询问, 每次询问影响O(logN)数量级的线段树结点, 每个结点O(logN)暴力建凸壳, 然后O(logN) ...
- 【SDOI2014】向量集
[SDOI2014]向量集 题目描述 我们分析一波: 假设我们询问\((A,B)\),\(x_i>x_j\)若 \[ A\cdot x_i+B\cdot y_i>A\cdot x_j+B\ ...
- 「SDOI2014」向量集 解题报告
「SDOI2014」向量集 维护一个向量集合,在线支持以下操作: A x y :加入向量 \((x, y)\): Q x y l r:询问第 \(L\) 个到第 \(R\) 个加入的向量与向量 \(( ...
- BZOJ3533 [Sdoi2014]向量集 【线段树 + 凸包 + 三分】
题目链接 BZOJ3533 题解 我们设询问的向量为\((x_0,y_0)\),参与乘积的向量为\((x,y)\) 则有 \[ \begin{aligned} ans &= x_0x + y_ ...
- Spark Mllib里的本地向量集(密集型数据集和稀疏型数据集概念、构成)(图文详解)
不多说,直接上干货! Local vector : 本地向量集 由两类构成:稀疏型数据集(spares)和密集型数据集(dense) (1).密集型数据集 例如一个向量数据(9,5,2,7),可以设 ...
- bzoj3533: [Sdoi2014]向量集
Description 维护一个向量集合,在线支持以下操作:"A x y (|x|,|y| < =10^8)":加入向量(x,y);" Q x y l r (|x| ...
- BZOJ3533:[SDOI2014]向量集(线段树,三分,凸包)
Description 维护一个向量集合,在线支持以下操作: "A x y (|x|,|y| < =10^8)":加入向量(x,y); " Q x y l r (| ...
- bzoj3533【Sdoi2014】向量集
题目描述 维护一个向量集合,在线支持以下操作:"A x y (|x|,|y| < =10^8)":加入向量(x,y);" Q x y l r (|x|,|y| &l ...
随机推荐
- k8s-架构中各个组件介绍
参考链接:https://github.com/opsnull/follow-me-install-kubernetes-cluster kubernetes 概述 1.kubernetes 是什么 ...
- framework7 总结之前遇到的问题和踩过的坑
官网上写的案例比较简单明了,我这里就将我使用时踩过的坑做一个总结,与大家共勉! 最近使用framework,基本全靠浏览官方文档,当然,有遇到了许多的错误,开始不知道哪里出问题也很着急,到最后发现问题 ...
- jQuery中cookie的简单操作
jQuery 可以通过 jquery.cookie.js 插件来操作 Cookie. 用NuGet安装:PM>Install-Package js-cookie -Version 官网:http ...
- Schnorr签名介绍
Schnorr签名介绍 来源 https://panzhibiao.com/2019/02/28/schnorr-sigature/ https://github.com/bitcoin/bitcoi ...
- Linux环境下:vmware安装Windows报错误-缺少所需的CD/DVD驱动器设备驱动程序
解决方法:将硬盘格式从SCSI改为IDE. 方法如下: 右键点击你新建的虚拟机名,点击最下面的setting,看到左侧第二行是hard disk 了么,你那里肯定是SCSI的,选中它,点最下面的rem ...
- Java自学-接口与继承 UML图
UML 图 步骤 1 : UML 图 -- 类之间的关系 UML-Unified Module Language 统一建模语言,可以很方便的用于描述类的属性,方法,以及类和类之间的关系 步骤 2 : ...
- 【Kafka】Exactly Once语义与事务
Kafka在0.11.0.0之前的版本中只支持At Least Once和At Most Once语义,尚不支持Exactly Once语义. 但是在很多要求严格的场景下,如使用Kafka处理交易数据 ...
- Vue学习之路由vue-router传参及嵌套小结(十)
一.路由传递参数: 1.使用query传值: <!DOCTYPE html> <html lang="en"> <head> <meta ...
- Map去重,去重value相同的元素,保留key最小的那个值
Map<Integer,String>,Integer代表时间撮,String代表文本信息去重函数:就是删除Map中value相同的元素,只保留key最小的那个元素 public stat ...
- Jvm调优积累的文章
Linux查看CPU和内存使用情况 stat命令查看jvm的GC情况 (以Linux为例) jvm优化必知系列——监控工具 Java JVM 参数设置大全
