「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. MySQL数据库性能优化思路与解决方法(一转)

     1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越 小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设 ...

  2. 高阶组件 HOC

    一. A higher-order component (HOC) is an advanced technique in React for reusing component logic. a h ...

  3. laravel get和all区别

      get ,all 都可以获取到模型 all 是直接获取所有,get 是在添加了许多约束之后获取模型,get前面如果不加约束条件的话,效果与all等同

  4. [转帖]关于CPU Cache -- 程序猿需要知道的那些事

    关于CPU Cache -- 程序猿需要知道的那些事 很早之前读过作者的blog 记得作者在facebook 工作.. 还写过mysql相关的内容 大拿 本文将介绍一些作为程序猿或者IT从业者应该知道 ...

  5. day 7-2 multiprocessing开启多进程

    一. multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu\_count\(\)查看),在python中大部分情况需要使用多 ...

  6. Vue 鼠标移入移出事件

    Vue 中鼠标移入移出事件 @mouseover和@mouseleave 然后绑定style   现在开始代码示例 <template> <div class="pc&qu ...

  7. Zookeeper的作用,在Hadoop及hbase中具体作用

    什么是Zookeeper,Zookeeper的作用是什么,在Hadoop及hbase中具体作用是什么 一.什么是Zookeeper ZooKeeper 顾名思义 动物园管理员,他是拿来管大象(Hado ...

  8. java学习之—数组的曾删改查

    /** * 数组的曾删改查 * Create by Administrator * 2018/6/8 0008 * 上午 9:54 **/ public class HighArray { priva ...

  9. PHPStorm从入门到精通

    1. 使用phpstorm+xdebug进行调试 首先,安装php的xdebug扩展 查看phpinfo中php的版本,php的安装位数,php的是否线程安全:根据这些下载对应的xdebug.dll ...

  10. LR运行负载测试场景-笔记

    控制虚拟用户的行为:通用如图方式 查看用户的运行信息 在控制器释放前释放集合点用户 记录运行时注释---scenario-execution notes Vuser 对话框:初始化.运行.停止运行用户 ...