「SDOI2014」向量集

维护一个向量集合,在线支持以下操作:

  1. A x y :加入向量 \((x, y)\);
  2. 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\)的最大值,化简一下就成了

\[y=-\frac{z}{w}x+\frac{ans}{w}
\]

最大化截距就讨论一下\(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」向量集 解题报告的更多相关文章

  1. 「SDOI2014」数数 解题报告

    「SDOI2014」数数 题目描述 我们称一个正整数 \(N\) 是幸运数,当且仅当它的十进制表示中不包含数字串集合 \(S\) 中任意一个元素作为其子串. 例如当 \(S=(\)22, 333, 0 ...

  2. LOJ 2664. 「NOI2013」向量内积 解题报告

    #2664. 「NOI2013」向量内积 两个 \(d\) 维向量 \(A=[a_1, a_2 ,...,a_d]\) 与 \(B=[b_1 ,b_2 ,...,b_d]\) 的内积为其相对应维度的权 ...

  3. 「FJOI2016」神秘数 解题报告

    「FJOI2016」神秘数 这题不sb,我挺sb的... 我连不带区间的都不会哇 考虑给你一个整数集,如何求这个神秘数 这有点像一个01背包,复杂度和值域有关.但是你发现01背包可以求出更多的东西,就 ...

  4. 「ZJOI2016」大森林 解题报告

    「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...

  5. 「SCOI2016」背单词 解题报告

    「SCOI2016」背单词 出题人sb 题意有毒 大概是告诉你,你给一堆n个单词安排顺序 如果当前位置为x 当前单词的后缀没在这堆单词出现过,代价x 这里的后缀是原意,但不算自己,举个例子比如abc的 ...

  6. 「NOI2015」寿司晚宴 解题报告

    「NOI2015」寿司晚宴 这个题思路其实挺自然的,但是我太傻了...最开始想着钦定一些,结果发现假了.. 首先一个比较套路的事情是状压前8个质数,后面的只会在一个数出现一次的再想办法就好. 然后发现 ...

  7. 「SCOI2015」国旗计划 解题报告

    「SCOI2015」国旗计划 蛮有趣的一个题 注意到区间互不交错,那么如果我们已经钦定了一个区间,它选择的下一个区间是唯一的,就是和它有交且右端点在最右边的,这个可以单调队列预处理一下 然后往后面跳拿 ...

  8. 「JLOI2015」骗我呢 解题报告?

    「JLOI2015」骗我呢 这什么神仙题 \[\color{purple}{Link}\] 可以学到的东西 对越过直线的东西翻折进行容斥 之类的..吧? Code: #include <cstd ...

  9. 「JLOI2015」城池攻占 解题报告

    「JLOI2015」城池攻占 注意到任意两个人的战斗力相对大小的不变的 可以离线的把所有人赛到初始点的堆里 然后做启发式合并就可以了 Code: #include <cstdio> #in ...

随机推荐

  1. Python之加环境变量

    1.python找文件是先去当前文件所在的文件夹下找,也就是bin目录下找 2.如果bin目录里找不到,再去python的环境变量里找 如果有pycharm,那么直接点右键-选择Mark Direct ...

  2. 安装使用swoole

    swoole首页:https://www.swoole.com/ 方法1:使用pecl安装 pecl install swoole 注意,php版本必须是7.0以及7.0以上的版本. 方法2:编译源码 ...

  3. 实验楼----PHP代码审计(sha1、md5)

    地址:http://www.shiyanbar.com/ctf/1787 题目:

  4. html js 表单提交前检测数据

    通过使用form的onsibmit来控制是否提交数据 返回值为真是提交,其他不变,示例如下: JS部分 function check() { var newPwd = document.getElem ...

  5. mysql之整型数据int

    mysql数据库设计,其中,对于数据性能优化,字段类型考虑很重要,mysql整型bigint.int.mediumint.smallint 和 tinyint的语法介绍,如下:1.bigint 从 - ...

  6. python读取文件内的IP信息 练习

    代码如下: #导包 import fileinput import re def readArw(): for line in fileinput.input(r"G:/raw.txt&qu ...

  7. java 工具

    JClassLib 4.2 发布了,该版本支持 Java 7 和 Java 8 的类文件属性查看. JClassLib不但是一个字节码阅读器而且还包含一个类库允许开发者读取,修改,写入Java Cla ...

  8. React Native之(支持iOS与Android)自定义单选按钮(RadioGroup,RadioButton)

    React Native之(支持iOS与Android)自定义单选按钮(RadioGroup,RadioButton) 一,需求与简单介绍 在开发项目时发现RN没有给提供RadioButton和Rad ...

  9. C\C++学习笔记 3

    C++记录7 函数指针: 函数名为地址, 地址指的是在机器指令存储的地址. double func(int line){ reture line*3.5;} void f(int line, doub ...

  10. [转帖]NUMA

    作者:ibless 来源:CSDN 原文:https://blog.csdn.net/ibless/article/details/80114009 其实 很早之前对这一块有了解 比较多的的是 CCN ...