「SDOI2014」向量集 解题报告
「SDOI2014」向量集
维护一个向量集合,在线支持以下操作:
A x y
:加入向量 \((x, y)\);Q x y l r
:询问第 \(L\) 个到第 \(R\) 个加入的向量与向量 \((x, y)\) 的点积的最大值。集合初始时为空。
对于所有的数据,\(1 \leq N \leq 4 \times 10^5\),操作中的向量坐标满足 \(|x|,|y| \leq 10^8\),询问满足 \(1 \leq L \leq R \leq T\),其中 \(T\) 为已经加入的向量个数。
一眼上去,线段树套KD-树???
然后觉得4e5根本跑不动,就一直没写。
看了题解才知道自己还是对凸优化不够熟悉,明明感觉可以凸优化,但搞不清楚式子怎么化
一般的套路是,对一个值询问一个集合,找其中一个运算后得到最值之类的,我们这时候把那个集合给弄成点集,把询问搞成最大截距或者最大斜率,就可以在凸包上三分了。
这个题询问点是\((z,w)\),即询问\(ans=xz+yw\)的最大值,化简一下就成了
\]
最大化截距就讨论一下\(w\)的正负,决定在上or下凸包上三分就可以了。
然后我们需要支持动态插入凸包,可以直接在线段树上模拟二进制分组,每次给线段树的区间加点,当某个区间加满了点,就构建凸包(没加满是不会被询问的)
复杂度\(O(n\log^2 n)\),LOJ上懒得卡了...
有个错误调了好久,以前写凸包的时候没注意,一定要以\(y\)作为第二关键字,否则在最右边的\(x\)上可能出现问题。
Code:
#include <cstdio>
#include <cctype>
#include <vector>
#include <algorithm>
#define ll long long
const int N=4e5+10;
using std::max;
int n,m,flag;
template <class T>
void read(T &x)
{
x=0;char c=getchar();bool f=0;
while(!isdigit(c)) f=c=='-'?1:0,c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x=f?-x:x;
}
inline int decode(int x,ll lastans){return flag?x^(lastans&0x7fffffff):x;}
struct Point
{
ll x,y;
Point(){}
Point(ll X,ll Y){x=X,y=Y;}
Point friend operator -(Point a,Point b){return Point(a.x-b.x,a.y-b.y);}
bool friend operator <(Point a,Point b){return a.x==b.x?a.y<b.y:a.x<b.x;}
};
ll Cross(Point a,Point b){return a.x*b.y-a.y*b.x;}
std::vector<Point> pot[N<<2],s[N<<2];
int Endro[N<<2],endro;
void ins(Point x,int id)
{
int tot=s[id].size()-1;
while(tot>=endro&&Cross(s[id][tot]-s[id][tot-1],x-s[id][tot])<=0) --tot,s[id].pop_back();
s[id].push_back(x);
}
void build(int id)
{
std::sort(pot[id].begin(),pot[id].end());
endro=1;
for(int i=0;i<pot[id].size();i++)
ins(pot[id][i],id);
endro=s[id].size();
Endro[id]=endro-1;
for(int i=pot[id].size()-2;~i;i--) ins(pot[id][i],id);
}
#define ls id<<1
#define rs id<<1|1
void change(int id,int l,int r,int p,Point ins)
{
pot[id].push_back(ins);
if(s[id].empty()&&pot[id].size()==r+1-l) build(id);
if(l==r) return;
int mid=l+r>>1;
if(p<=mid) change(ls,l,mid,p,ins);
else change(rs,mid+1,r,p,ins);
}
ll cal(int x,int y,Point d)
{
return d.x*x+d.y*y;
}
ll yuu(int id,int x,int y)
{
int endro=s[id].size()-1;
if(y==0) return max(s[id][0].x*x,s[id][Endro[id]].x*x);
int l,r;
if(y>0) l=Endro[id],r=endro;
else l=0,r=Endro[id];
while(l<r)
{
int mid=l+r>>1;
if(cal(x,y,s[id][mid])<cal(x,y,s[id][mid+1])) l=mid+1;
else r=mid;
}
return cal(x,y,s[id][l]);
}
ll query(int id,int L,int R,int l,int r,int x,int y)
{
if(l==L&&r==R) return yuu(id,x,y);
int Mid=L+R>>1;
if(r<=Mid) return query(ls,L,Mid,l,r,x,y);
else if(l>Mid) return query(rs,Mid+1,R,l,r,x,y);
else return max(query(ls,L,Mid,l,Mid,x,y),query(rs,Mid+1,R,Mid+1,r,x,y));
}
int main()
{
char op[10];read(n),scanf("%s",op);
if(op[0]!='E') flag=1;
ll las=0;
for(int x,y,l,r,i=1;i<=n;i++)
{
scanf("%s",op);
if(op[0]=='A')
{
read(x),read(y);
x=decode(x,las),y=decode(y,las);
change(1,1,n,++m,Point(x,y));
}
else
{
read(x),read(y),read(l),read(r);
x=decode(x,las),y=decode(y,las);
l=decode(l,las),r=decode(r,las);
printf("%lld\n",las=query(1,1,n,l,r,x,y));
}
}
return 0;
}
「SDOI2014」向量集 解题报告的更多相关文章
- 「SDOI2014」数数 解题报告
「SDOI2014」数数 题目描述 我们称一个正整数 \(N\) 是幸运数,当且仅当它的十进制表示中不包含数字串集合 \(S\) 中任意一个元素作为其子串. 例如当 \(S=(\)22, 333, 0 ...
- LOJ 2664. 「NOI2013」向量内积 解题报告
#2664. 「NOI2013」向量内积 两个 \(d\) 维向量 \(A=[a_1, a_2 ,...,a_d]\) 与 \(B=[b_1 ,b_2 ,...,b_d]\) 的内积为其相对应维度的权 ...
- 「FJOI2016」神秘数 解题报告
「FJOI2016」神秘数 这题不sb,我挺sb的... 我连不带区间的都不会哇 考虑给你一个整数集,如何求这个神秘数 这有点像一个01背包,复杂度和值域有关.但是你发现01背包可以求出更多的东西,就 ...
- 「ZJOI2016」大森林 解题报告
「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...
- 「SCOI2016」背单词 解题报告
「SCOI2016」背单词 出题人sb 题意有毒 大概是告诉你,你给一堆n个单词安排顺序 如果当前位置为x 当前单词的后缀没在这堆单词出现过,代价x 这里的后缀是原意,但不算自己,举个例子比如abc的 ...
- 「NOI2015」寿司晚宴 解题报告
「NOI2015」寿司晚宴 这个题思路其实挺自然的,但是我太傻了...最开始想着钦定一些,结果发现假了.. 首先一个比较套路的事情是状压前8个质数,后面的只会在一个数出现一次的再想办法就好. 然后发现 ...
- 「SCOI2015」国旗计划 解题报告
「SCOI2015」国旗计划 蛮有趣的一个题 注意到区间互不交错,那么如果我们已经钦定了一个区间,它选择的下一个区间是唯一的,就是和它有交且右端点在最右边的,这个可以单调队列预处理一下 然后往后面跳拿 ...
- 「JLOI2015」骗我呢 解题报告?
「JLOI2015」骗我呢 这什么神仙题 \[\color{purple}{Link}\] 可以学到的东西 对越过直线的东西翻折进行容斥 之类的..吧? Code: #include <cstd ...
- 「JLOI2015」城池攻占 解题报告
「JLOI2015」城池攻占 注意到任意两个人的战斗力相对大小的不变的 可以离线的把所有人赛到初始点的堆里 然后做启发式合并就可以了 Code: #include <cstdio> #in ...
随机推荐
- KubeCon CloudNativeCon China 2019
KubeCon CloudNativeCon China 2019 - LF Asia, LLChttps://events.linuxfoundation.cn/events/kubecon-clo ...
- 百度地图api在Html中显示,在jsp页面中不显示解决方法
在jsp页面中显示如下 但是在html中正常显示. 原来的代码如下: <script type="text/javascript" src="http://api. ...
- Day 5-6 反射和内置方法之item系列
python面向对象中的反射:通过字符串的形式操作对象相关的属性.python中的一切事物都是对象(都可以使用反射) #!_*_ coding:utf-8 _*_ class People: def ...
- longquan
/** * 登录后将数据填写到主数据 */ public void login(String login_nr) { //File f = new File(android.os.Environmen ...
- Mapper动态代理方式
开发规范 Mapper接口开发方法只需要程序员编写Mapper接口(相当于Dao接口),由Mybatis框架根据接口定义创建接口的动态代理对象,代理对象的方法体同Dao接口实现类方法. Mapper接 ...
- 莫烦theano学习自修第七天【回归结果可视化】
1.代码实现 from __future__ import print_function import theano import theano.tensor as T import numpy as ...
- python数据结构与算法第九天【选择排序】
1.选择排序的原理 2.代码实现 def selection_sort(alist): n = len(alist) # 需要进行n-1次选择操作 for i in range(n-1): # 记录最 ...
- Python——Flask框架——程序的基本结构
一.安装 pip install flask 二.初始化 from flask import Flask app = Flash(__name__) 三.路由:处理URL和函数之间的关系的程序称为路由 ...
- 实用的几个JS新特性(es 2016)
在Chrome 55下测试,可用. 1.箭头函数(arrow function) 以前写的匿名函数是这样的 function(){}, 现在可以简单写成这样()=>{} 如果直接return,没 ...
- 在 Web 页面使用 VLC 插件播放 m3u8 视频流 (360 极速模式)
1. 背景 公司有个旧项目需要添加在线播放 m3u8 视频流,但是该流不知道什么原因使用 Video.js 或 hls.js 均无法播放,最后找到解决方案可使用 VLC 插件播放(360 极速模式下) ...