「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. 原生node路由操作以及注意事项

    var http = require("http"); var url = require("url"); var ejs = require("ej ...

  2. liunx 运维知识三部分

    一. 用户级用户组相关 二. 文件属性和链接知识及磁盘已满故障案例 三. 通配符 四. 特殊符号 五. 基础正则 六. 扩展正则 七. sed实践 八. awk实践

  3. Dom4j解析

    dom4j-1.6.1.jar, 这个包提供了xml解析相关的方法. 这里做一个记录,微信公众号里需要对HttpServletRequest做解析,实际上也可以用dom4j提供的方法进行解析转换. 这 ...

  4. FindBugs-IDEA插件的使用

    前言 Findbugs很多人都并不陌生,Eclipse中有插件可以帮助查找代码中隐藏的bug,IDEA中也有这款插件.这个插件可以帮助我们查找隐藏的bug,比较重要的功能就是查找潜在的null指针.  ...

  5. shell expr用法

    expr 计算整数变量值 使用方法如下: linux-zpycfm:/home/test/shell # s=+ -bash: +: command not found linux-zpycfm:/h ...

  6. 安装VC++2015运行库时出现0x80240037错误

    很多时候,当我们将开发好的软件部署到用户的机器上时总会出现各种意想不到的错误,最近在一台原版Windows7系统的电脑上安装VC++运行库的时候,莫名的出现安装失败,然后错误代码为:0x8024003 ...

  7. CSS3圆角详解(border-radius)

    1.CSS3圆角的优点 传统的圆角生成方案,必须使用多张图片作为背景图案.CSS3的出现,使得我们再也不必浪费时间去制作这些图片了,而且还有其他多个优点: 减少维护的工作量.图片文件的生成.更新.编写 ...

  8. How to remove unwant Explorer Context Menu

    HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Directory\shell

  9. Military Problem CodeForces 1006E (dfs序)

    J - Military Problem CodeForces - 1006E 就是一道dfs序的问题 给定一个树, 然后有q次询问. 每次给出u,k, 求以u为根的子树经过深搜的第k个儿子,如果一个 ...

  10. 思路:当一个表嵌套另一个表时候 只需在dao中引入该mapper即可 进行正常的数据插入 查询 修改等