正题

题目链接:https://www.luogu.com.cn/problem/P3309


题目大意

\(n\)个操作

  1. 在序列末尾加入一个向量\((x,y)\)
  2. 询问加入的第\(l\sim r\)个向量中的一个向量和\((x,y)\)的点积最大值

强制在线,点积的定义为\(x_1x_2+y_1y_2\)


解题思路

如果对于一个\((x,y)\)对于两个\((x_1,y_1)\)和\((x_2,y_2)\)如果后者更大那么有

\[x_2x+y_2y>x_1x+y_1y\Rightarrow \frac{y}{x}\leq \frac{x_2-x_1}{y_2-y_1}
\]

好像和斜率有关,可以维护凸壳来做,因为\(y\)可能是负数,如果是负数的时候就要求的是下凸壳了,所以两个凸壳都要维护。

因为强制在线所以上不了传统艺能\(\text{CDQ}\)

那怎么动态维护区间凸壳,平衡树支持动态插入但不支持区间问题。所以考虑线段树,因为一个位置修改了之后就不会再修改,而且是从左往右加的,可以利用这个性质。

每次我们修改一个位置后,如果一个区间\([L,R]\)的节点内已经插入了\(R-L+1\)个向量(也就是都插完了)的话就直接把它的两个儿子的凸壳合并起来。

然后询问的时候分成\(log\ n\)个区间询问的答案取最大值就好了。

合并凸壳的是用归并排序的话时间复杂度\(O(n\log n)\)


code

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<vector>
  5. #define ll long long
  6. using namespace std;
  7. struct point{
  8. ll x,y;
  9. point(ll xx=0,ll yy=0)
  10. {x=xx;y=yy;return;}
  11. }z;
  12. point operator+(point x,point y)
  13. {return point(x.x+y.x,x.y+y.y);}
  14. point operator-(point x,point y)
  15. {return point(x.x-y.x,x.y-y.y);}
  16. ll operator^(point x,point y)
  17. {return x.x*y.y-x.y*y.x;}
  18. ll operator*(point x,point y)
  19. {return x.x*y.x+x.y*y.y;}
  20. bool operator<(point x,point y)
  21. {return (x.x==y.x)?x.y<y.y:x.x<y.x;}
  22. const ll N=4e5+10;
  23. char pe[3];
  24. ll n,num,siz[N<<2];
  25. vector<point> v[N<<2][2],tmp;
  26. void Make(ll x){
  27. ll ls=x*2,rs=x*2+1;
  28. for(ll k=0;k<2;k++){
  29. ll i=0,j=0,l1=v[ls][k].size()-1,l2=v[rs][k].size()-1;
  30. tmp.clear();
  31. while(i<=l1||j<=l2){
  32. if(i>l1||(j<=l2&&v[rs][k][j]<v[ls][k][i]))
  33. tmp.push_back(v[rs][k][j]),j++;
  34. else tmp.push_back(v[ls][k][i]),i++;
  35. }
  36. ll cnt=0;
  37. for(ll i=0;i<tmp.size();i++){
  38. while(cnt>1&&((v[x][k][cnt-1]-v[x][k][cnt-2])^(tmp[i]-v[x][k][cnt-1]))>=0)
  39. v[x][k].pop_back(),cnt--;
  40. v[x][k].push_back(tmp[i]);cnt++;
  41. }
  42. }
  43. return;
  44. }
  45. ll Calc(ll x,point p){
  46. ll f=0;
  47. if(p.y<0)p=z-p,f^=1;
  48. ll l=0,r=v[x][f].size()-2;
  49. while(l<=r){
  50. ll mid=(l+r)>>1;
  51. point tmp=v[x][f][mid+1]-v[x][f][mid];tmp.x*=-1;
  52. if(p.x*tmp.x>=p.y*tmp.y)r=mid-1;
  53. else l=mid+1;
  54. }
  55. return p*v[x][f][l];
  56. }
  57. void Change(ll x,ll L,ll R,ll pos,point p){
  58. if(L==R){
  59. v[x][0].push_back(p);
  60. v[x][1].push_back(z-p);
  61. return;
  62. }
  63. ll mid=(L+R)>>1;siz[x]++;
  64. if(pos<=mid)Change(x*2,L,mid,pos,p);
  65. else Change(x*2+1,mid+1,R,pos,p);
  66. if(siz[x]==R-L+1)Make(x);
  67. }
  68. ll Ask(ll x,ll L,ll R,ll l,ll r,point p){
  69. if(L==l&&R==r)return Calc(x,p);
  70. ll mid=(L+R)>>1;
  71. if(r<=mid)return Ask(x*2,L,mid,l,r,p);
  72. if(l>mid)return Ask(x*2+1,mid+1,R,l,r,p);
  73. return max(Ask(x*2,L,mid,l,mid,p),Ask(x*2+1,mid+1,R,mid+1,r,p));
  74. }
  75. void dc(ll &x,ll lastans) {
  76. if(pe[0]=='E')return;
  77. x=x^(lastans&0x7fffffff);
  78. return;
  79. }
  80. signed main()
  81. {
  82. scanf("%lld%s",&n,pe);
  83. ll last=0;
  84. for(ll i=1;i<=n;i++){
  85. char op[3];ll x,y,l,r;
  86. scanf("%s%lld%lld",op,&x,&y);
  87. dc(x,last);dc(y,last);
  88. if(op[0]=='A'){
  89. ++num;
  90. Change(1,1,n,num,point(x,y));
  91. }
  92. else{
  93. scanf("%lld%lld",&l,&r);dc(l,last);dc(r,last);
  94. printf("%lld\n",last=Ask(1,1,n,l,r,point(x,y)));
  95. }
  96. }
  97. return 0;
  98. }

P3309-[SDOI2014]向量集【线段树,凸壳】的更多相关文章

  1. BZOJ 3533: [Sdoi2014]向量集( 线段树 + 三分 )

    答案一定是在凸壳上的(y>0上凸壳, y<0下凸壳). 线段树维护, 至多N次询问, 每次询问影响O(logN)数量级的线段树结点, 每个结点O(logN)暴力建凸壳, 然后O(logN) ...

  2. BZOJ3533:[SDOI2014]向量集(线段树,三分,凸包)

    Description 维护一个向量集合,在线支持以下操作: "A x y (|x|,|y| < =10^8)":加入向量(x,y); " Q x y l r (| ...

  3. 【bzoj3533】[Sdoi2014]向量集 线段树+STL-vector维护凸包

    题目描述 维护一个向量集合,在线支持以下操作:"A x y (|x|,|y| < =10^8)":加入向量(x,y);"Q x y l r (|x|,|y| < ...

  4. bzoj 3533: [Sdoi2014]向量集 线段树维护凸包

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3533 题解: 首先我们把这些向量都平移到原点.这样我们就发现: 对于每次询问所得到的an ...

  5. bzoj 3533 [Sdoi2014]向量集 线段树+凸包+三分(+动态开数组) 好题

    题目大意 维护一个向量集合,在线支持以下操作: "A x y (|x|,|y| < =10^8)":加入向量(x,y); "Q x y l r (|x|,|y| & ...

  6. [SDOI2014][BZOJ3533] 向量集 [线段树+凸包]

    题面 BZOJ传送门 思路 首先当然是推式子 对于一个询问点$(x_0,y_0$和给定向量$(x_1,y_1)$来说,点积这么表达: $A=x_0x_1+y_0y_1$ 首先肯定是考虑大小关系:$x_ ...

  7. P3309 [SDOI2014]向量集

    传送门 达成成就:一人独霸三页提交 自己写的莫名其妙MLE死都不知道怎么回事,照着题解打一直RE一个点最后发现竟然是凸包上一个点求错了--四个半小时就一直用来调代码了-- 那么我们只要维护好这个凸壳, ...

  8. 【BZOJ4311】向量(线段树分治,斜率优化)

    [BZOJ4311]向量(线段树分治,斜率优化) 题面 BZOJ 题解 先考虑对于给定的向量集,如何求解和当前向量的最大内积. 设当前向量\((x,y)\),有两个不同的向量\((u1,v1),(u2 ...

  9. UVA1455 - Kingdom(并查集 + 线段树)

    UVA1455 - Kingdom(并查集 + 线段树) 题目链接 题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum ...

随机推荐

  1. 浅谈 asp.net core web api

    希望通过本文能够了解如下内容: ControllerBase Attributes Action的返回值类型 ControllerBase 当我们开始实际上项目, 真正实操 anc 时, 肯定会用到 ...

  2. (四)HXDZ-30102-ACC检测心率血氧数据并通过串口助手显示

    主要参考模块说明书 写在前面的话 硬件原理我是真的搞不明白,所以心率血氧传感器数据检测就是模块卖家自带的代码... 我使用HXDZ-30102-ACC传感器也是偶然在网上检索到的,集成心率血氧和三轴加 ...

  3. return 和 return false 的区别

    return返回null,起到中断方法执行的效果,只要不return false事件处理函数将会继续执行,表单将提交. return false,事件处理函数会取消事件,不再继续向下执行.比如表单将终 ...

  4. Git pull and push

    转自:https://blog.csdn.net/qq_41306423/article/details/101701991 关于 git pull 和 git pull origin develop ...

  5. 微信小程序学习笔记四 自定义组件

    1. 自定义组件 类似Vue或react中的自定义组件 小程序允许我们使用自定义组件的方式来构建页面 1.1 创建自定义组件 类似于页面, 一个自定义组件由json wxml wxss js 4个文件 ...

  6. opencv入门系列教学(四)处理鼠标事件

    一.鼠标事件的简单演示 opencv中的鼠标事件,值得是任何与鼠标相关的任何事物,例如左键按下,左键按下,左键双击等.我们先来看看鼠标事件有哪些,在python中执行下面代码: import cv2 ...

  7. rabbitMq镜像集群

    rabbitMq延迟投递的方案 1 把消息记录到数据路,通过定时器进行刷新 2 TTL 加上死信队列 :通过路由把过期的消息同步到死信队列,通过死信队列的消费者进行消费 3

  8. TDSQL MySQL版基本原理-水平分表 读写分离 弹性扩展 强同步

    TDSQL MySQL版(TDSQL for MySQL)是部署在腾讯云上的一种支持自动水平拆分.Shared Nothing 架构的分布式数据库.TDSQL MySQL版 即业务获取的是完整的逻辑库 ...

  9. 七、Abp vNext 基础篇丨文章聚合功能下

    介绍 不好意思这篇文章应该早点更新的,这几天在忙CICD的东西没顾得上,等后面整好了CICD我也发2篇文章讲讲,咱们进入正题,这一章来补全剩下的 2个接口和将文章聚合进行完善. 开工 上一章大部分业务 ...

  10. Linux/CentOS基础命令1

    一.系统相关运行命令1.系统关机命令:shutdown# shutdown 关机 Shutdown scheduled for Fri 2019-03-29 11:36:45 CST, use 'sh ...