【SDOI2014】向量集
【SDOI2014】向量集
我们分析一波:
假设我们询问\((A,B)\),\(x_i>x_j\)若
A\cdot(x_i-x_j)>B\cdot(y_j-y_i)
\]
当\(B>0\)
\]
否则
\]
所以,对于\(B>0\),我们在上凸壳上三分,否则在下凸壳上三分。\(B=0\)随意。
三分细节:条件是\(r-l\geq 3\),然后两个端点是\(\frac{l+l+r}{3}\)以及\(\frac{l+r+r}{3}\)。
代码:
#include<bits/stdc++.h>
#define ll long long
#define inf 1e16
#define eps 1e-7
#define N 400005
using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
int n;
ll ans;
char type;
int decode(int x) {return (type!='E')?x^(ans&0x7fffffff):x;}
struct point {
double x,y;
bool operator <(const point &a)const {return x<a.x;}
};
double slope(const point &a,const point &b) {
if(fabs(a.x-b.x)<eps) return a.y<b.y?inf:-inf;
return (a.y-b.y)/(a.x-b.x);
}
double cdot(const point &a,const point &b) {return a.x*b.x+a.y*b.y;}
vector<point>tem;
struct Convex {
vector<point>st;
int size() {return st.size();}
void Insert(point a) {st.push_back(a);}
void build(int flag) {
sort(st.begin(),st.end());
tem.clear();
if(flag) {
//上凸壳
for(int i=0;i<st.size();i++) {
while(tem.size()>1&&slope(tem[tem.size()-2],tem[tem.size()-1])<slope(tem[tem.size()-1],st[i])+eps) tem.pop_back();
tem.push_back(st[i]);
}
} else {
//下凸壳
for(int i=0;i<st.size();i++) {
while(tem.size()>1&&slope(tem[tem.size()-2],tem[tem.size()-1])+eps>slope(tem[tem.size()-1],st[i])) tem.pop_back();
tem.push_back(st[i]);
}
}
st=tem;
}
ll query(point a) {
int l=0,r=st.size()-1;
while(r-l>=3) {
int lmid=(l+l+r)/3;
int rmid=(l+r+r)/3;
if(cdot(st[lmid],a)>cdot(st[rmid],a)) r=rmid;
else l=lmid;
}
double ans=-inf;
for(;l<=r;l++) ans=max(ans,cdot(st[l],a));
return (ll)ans;
}
};
struct tree {
int l,r;
Convex u,d;
}tr[N<<2];
void build(int v,int l,int r) {
tr[v].l=l,tr[v].r=r;
if(l==r) return ;
int mid=l+r>>1;
build(v<<1,l,mid),build(v<<1|1,mid+1,r);
}
void Insert(int v,int p,point a) {
tr[v].u.Insert(a);
tr[v].d.Insert(a);
if(tr[v].u.size()==tr[v].r-tr[v].l+1) {
tr[v].u.build(1);
tr[v].d.build(0);
}
if(tr[v].l==tr[v].r) return ;
int mid=tr[v].l+tr[v].r>>1;
if(p<=mid) Insert(v<<1,p,a);
else Insert(v<<1|1,p,a);
}
ll query(int v,int l,int r,point a) {
if(tr[v].l>r||tr[v].r<l) return -inf;
if(l<=tr[v].l&&tr[v].r<=r) return a.y>0?tr[v].u.query(a):tr[v].d.query(a);
return max(query(v<<1,l,r,a),query(v<<1|1,l,r,a));
}
int main() {
n=Get();
scanf("%c",&type);
build(1,1,n);
char op;
point a;
int l,r;
int now=0;
while(n--) {
while(op=getchar(),!isalpha(op));
if(op=='A') {
now++;
a.x=decode(Get()),a.y=decode(Get());
Insert(1,now,a);
} else {
a.x=decode(Get()),a.y=decode(Get());
l=decode(Get()),r=decode(Get());
cout<<(ans=query(1,l,r,a))<<"\n";
}
}
return 0;
}
【SDOI2014】向量集的更多相关文章
- BZOJ 3533: [Sdoi2014]向量集( 线段树 + 三分 )
答案一定是在凸壳上的(y>0上凸壳, y<0下凸壳). 线段树维护, 至多N次询问, 每次询问影响O(logN)数量级的线段树结点, 每个结点O(logN)暴力建凸壳, 然后O(logN) ...
- BZOJ3533 [Sdoi2014]向量集 【线段树 + 凸包 + 三分】
题目链接 BZOJ3533 题解 我们设询问的向量为\((x_0,y_0)\),参与乘积的向量为\((x,y)\) 则有 \[ \begin{aligned} ans &= x_0x + y_ ...
- 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]向量集 线段树+STL-vector维护凸包
题目描述 维护一个向量集合,在线支持以下操作:"A x y (|x|,|y| < =10^8)":加入向量(x,y);"Q x y l r (|x|,|y| < ...
- bzoj 3533: [Sdoi2014]向量集 线段树维护凸包
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3533 题解: 首先我们把这些向量都平移到原点.这样我们就发现: 对于每次询问所得到的an ...
- bzoj 3533 [Sdoi2014]向量集 线段树+凸包+三分(+动态开数组) 好题
题目大意 维护一个向量集合,在线支持以下操作: "A x y (|x|,|y| < =10^8)":加入向量(x,y); "Q x y l r (|x|,|y| & ...
- Sdoi2014 向量集
题目描述 题解: 码力太差重构之后才$A……$ 首先求向量点积最大很容易想到凸包, 设已知$(x_0,y_0)$,求$(x,y)$满足$(x,y)*(x_0,y_0)>=(x',y')*(x_0 ...
- P3309 [SDOI2014]向量集
传送门 达成成就:一人独霸三页提交 自己写的莫名其妙MLE死都不知道怎么回事,照着题解打一直RE一个点最后发现竟然是凸包上一个点求错了--四个半小时就一直用来调代码了-- 那么我们只要维护好这个凸壳, ...
- SDOI 2014 向量集
[SDOI2014]向量集 题目描述 维护一个向量集合,在线支持以下操作: - "A x y (|x|,|y| < =10^8)":加入向量(x,y); - " Q ...
随机推荐
- c#调用腾讯云API的实例
//获取时间戳 .net framework /* DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1 ...
- 【C#】list 去重(转载)
Enumerable.Distinct 方法 是常用的LINQ扩展方法,属于System.Linq的Enumerable方法,可用于去除数组.集合中的重复元素,还可以自定义去重的规则. 有两个重载方法 ...
- JSJ——java基本概念二
当Java虚拟机启动执行时,它会寻找你在命令列所指定的类.每个Java程序最少都会有一个类以及一个main().每个应用程序只有一个main()函数.然后它会锁定像下面这样一个特定的方法: publi ...
- 【Mysql】常用命令
登录mysql -uroot -p 查看有哪些数据库show databases; 创建一个普通用户 sa ,密码是 some_passCREATE USER 'sa'@'%' IDENTIFIED ...
- java安全管理器SecurityManager介绍
java安全管理器类SecurityManager简单剖析: javadoc介绍: SecurityManager是一个允许应用实现一种安全策略的类.它允许一个应用去明确,在执行一个可能安全或者敏感的 ...
- Python 部分系统类的常用方法整理
下面是常用的几个系统类的常用方法整理: list: 列表[1, 2,...] set: 集合,无重复元素{1, 2,...} str: 字符串 dict: 字典{a:'a', b:'b',...} T ...
- 处理JavaScript异常的正确姿势
译者按: 错误是无法避免的,妥善处理它才是最重要的! 原文: A Guide to Proper Error Handling in JavaScript Related Topics: 译者: Fu ...
- C# 动态输出Dos命令执行结果
本文以一个简单的小例子讲解如何将命令行信息实时的输出到文本框中.仅供学习分享使用,如有不足之处,还请指正. 概述 在C#程序开发过程中,有时需要运行其它的程序并获得输出的结果来进行进一步的处理.一般第 ...
- Kotlin入门教程——目录索引
Kotlin是谷歌官方认可的Android开发语言,Android Studio从3.0版本开始就内置了Kotlin,所以未来在App开发中Kotlin取代Java是大势所趋,就像当初Android ...
- java笔记----java新建生成用户定义注释
${filecomment} ${package_declaration} /** * @author ${user} * @date 创建时间:${date} ${time} * @version ...