bzoj 3533: [Sdoi2014]向量集 线段树+凸包+二分
来源:互联网 发布:电子数据交换的意思 编辑:程序博客网 时间:2024/05/23 15:39
题意
维护一个向量集合,在线支持以下操作:
“A x y (|x|,|y| < =10^8)”:加入向量(x,y);
” Q x y l r (|x|,|y| < =10^8,1 < =L < =R < =T,其中T为已经加入的向量个数)询问第L个到第R个加入的向量与向量(x,y)的点积的最大值。
集合初始时为空。强制在线。
1 < =N < =4×10^5
分析
世界上最开心的事情莫过于一遍AC计算几何+数据结构题~~
答案是要求
现在只讨论
显然最优解必然在点集的下凸壳上。那么我们可以考虑把下凸壳求出来,然后在上面二分即可。
网上很多题解都是用三分,的确这是个单峰函数,但考虑到是定义在正整数集上的单峰函数,所以实际上是可以用二分来求的。
现在要求的是一个区间的下凸壳,考虑用线段树来维护。
但求下凸壳的复杂度是
这里有一个很机智的办法,就是注意到若该区间包含一个还没被加入的位置,则一定不会被询问到。所以我们每加入一个点,就暴力把那些右端点为该点的区间跑一遍下凸壳即可。
若
代码
#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<vector>using namespace std;typedef long long LL;const int N=400005;const LL inf=100000000000000000;int n,tot,que[N];pair<int,int> tmp[N],a[N];struct tree{vector<pair<int,int> > u,d;}t[N*5];LL ans;int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}inline int decode(int x,LL ans){ return x^(ans&0x7fffffff);}double get_k(pair<int,int> x,pair<int,int> y){ return (double)(x.second-y.second)/(x.first-y.first);}void build(int d,int l,int r){ int tot=0; for (int i=l;i<=r;i++) tmp[++tot]=a[i]; sort(tmp+1,tmp+tot+1); for (int i=tot;i>1;i--) if (tmp[i].first==tmp[i-1].first) tmp[i-1].second=tmp[i].second; tot=unique(tmp+1,tmp+tot+1)-tmp-1; int head=1,tail=1;que[1]=1; for (int i=2;i<=tot;i++) { while (head<tail&&get_k(tmp[que[tail-1]],tmp[que[tail]])<get_k(tmp[que[tail]],tmp[i])) tail--; que[++tail]=i; } while (head<=tail) t[d].u.push_back(tmp[que[head]]),head++; tot=0; for (int i=l;i<=r;i++) tmp[++tot]=a[i]; sort(tmp+1,tmp+tot+1); for (int i=1;i<tot;i++) if (tmp[i].first==tmp[i+1].first) tmp[i+1].second=tmp[i].second; tot=unique(tmp+1,tmp+tot+1)-tmp-1; head=1;tail=1;que[1]=1; for (int i=2;i<=tot;i++) { while (head<tail&&get_k(tmp[que[tail-1]],tmp[que[tail]])>get_k(tmp[que[tail]],tmp[i])) tail--; que[++tail]=i; } while (head<=tail) t[d].d.push_back(tmp[que[head]]),head++;}LL get_ans(pair<int,int> x,pair<int,int> y){ return (LL)x.first*y.first+(LL)x.second*y.second;}LL query(int d,pair<int,int> p){ int x=p.first,y=p.second; if (!y) return max(x*t[d].d[0].first,x*t[d].d[t[d].d.size()-1].first); if (y<0) { int l=0,r=t[d].d.size()-2; while (l<=r) { int mid=(l+r)/2; if (get_ans(t[d].d[mid],p)>get_ans(t[d].d[mid+1],p)) r=mid-1; else l=mid+1; } return get_ans(t[d].d[r+1],p); } else { int l=0,r=t[d].u.size()-2; while (l<=r) { int mid=(l+r)/2; if (get_ans(t[d].u[mid],p)>get_ans(t[d].u[mid+1],p)) r=mid-1; else l=mid+1; } return get_ans(t[d].u[r+1],p); }}void ins(int d,int l,int r,int x){ if (r==x) build(d,l,r); if (l==r) return; int mid=(l+r)/2; if (x<=mid) ins(d*2,l,mid,x); else ins(d*2+1,mid+1,r,x);}LL query(int d,int l,int r,int x,int y,pair<int,int> p){ if (x>y) return -inf; if (l==x&&r==y) return query(d,p); int mid=(l+r)/2; return max(query(d*2,l,mid,x,min(y,mid),p),query(d*2+1,mid+1,r,max(x,mid+1),y,p));}int main(){ n=read(); char ty[2];scanf("%s",ty); for (int i=1;i<=n;i++) { char op[2]; scanf("%s",op); if (op[0]=='A') { int x=read(),y=read(); if (ty[0]!='E') x=decode(x,ans),y=decode(y,ans); a[++tot]=make_pair(x,y); ins(1,1,n,tot); } else { int x=read(),y=read(),l=read(),r=read(); if (ty[0]!='E') x=decode(x,ans),y=decode(y,ans),l=decode(l,ans),r=decode(r,ans); printf("%lld\n",ans=query(1,1,n,l,r,make_pair(x,y))); } } return 0;}
阅读全文
0 0
- bzoj 3533: [Sdoi2014]向量集 线段树+凸包+二分
- BZOJ 3533 Sdoi2014 向量集 线段树+凸包+三分
- bzoj 3533 [Sdoi2014]向量集 凸包
- 【BZOJ】【P3533】【Sdoi2014】【向量集】【题解】【线段树+凸包+三分】
- 【bzoj3533】[Sdoi2014]向量集 三分+线段树+凸包
- Bzoj3533:[Sdoi2014]向量集:线段树+凸包+三分
- BZOJ 3533 Sdoi2014 向量集
- BZOJ 4311: 向量(线段树分治+凸包+三分)
- [树链剖分 线段树] BZOJ 3531 [Sdoi2014]旅行
- BZOJ 3531 [SDOI2014]旅行 树链剖分+线段树
- bzoj 3531: [Sdoi2014]旅行 线段树+树链剖分
- BZOJ 3531 [Sdoi2014]旅行 树链剖分 线段树
- 【SDOI2014】【BZOJ3533】向量集
- bzoj3533【SDOI2014】向量集
- BZOJ3533: [Sdoi2014]向量集
- BZOJ3533: [Sdoi2014]向量集
- bzoj3533: [Sdoi2014]向量集
- BZOJ3533 SDOI2014 向量集
- HDU
- 51Nod 1262 扔球
- day20
- Drupal7 安装成功后,管理员登录成功,但是提示拒绝访问
- Quartz教程 第6课 CronTrigger
- bzoj 3533: [Sdoi2014]向量集 线段树+凸包+二分
- 四大组件--ContentProvider
- oracle对约束的一些操作
- C++中将链表转换为数组描述的线性表
- 不说技术,不说潜规则, 说说职场上的小细节
- Linux Shell 基础(二)
- JavaWeb---Servlet的请求和响应
- Android 属性动画和添加图片
- 洛谷P1512 伊甸园日历游戏