向量集
题目描述:扔个传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3533
题解
首先,可以证明答案一定在凸壳上。
若y>0,则答案在上凸壳上找到,若y<0,则在下凸壳上找到。
所以,我们需要分别维护区间的上下凸壳,也就是一个凸包。
这里可以利用线段树进行维护。
显然,一个线段树上的区间可以被查询到,当且仅当这个区间的右端点已经被更新。
因此,每加入一个点,就对满的区间求凸包。
查询操作只需在凸包上进行三分即可。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define ll long long
#define N 400005
#define inf 1e15
using namespace std;
int n,m,cnt,tot,flag;ll la;
struct node{
ll x,y;
bool operator<(const node &p)
const{return x<p.x||(x==p.x&&y<p.y);}
node operator-(const node &p)
const{return (node){x-p.x,y-p.y};}
ll operator*(const node &p)
const{return x*p.x+y*p.y;}
ll operator^(const node &p)
const{return x*p.y-y*p.x;}
}s[N*40],p[N],q[N*2],po[N];
struct point{
int L1,R1,L2,R2;
void build(int x,int y)
{
int len=y-x+1,top=0;
for(int i=1;i<=len;i++)p[i]=po[x+i-1];
sort(p+1,p+len+1);
for(int i=1;i<=len;i++)
{
while(top&&(q[top]-q[top-1]^p[i]-q[top])<=0)top--;
q[++top]=p[i];
}
int sum=top;
for(int i=len;i;i--)
{
while(top>sum&&(q[top]-q[top-1]^p[i]-q[top])<=0)top--;
q[++top]=p[i];
}
L1=tot+1;R1=L1+sum-1;L2=R1;R2=L1+top-1;
for(int i=1;i<=top;i++)s[++tot]=q[i];
}
ll qry(int x,int y)
{
int l,r;ll res=-inf;node p=(node){x,y};
if(y<0)l=L1,r=R1;
else l=L2,r=R2;
while(r-l>3)
{
int len=(r-l+1)/3,lx=l+len,rx=r-len;
if(s[lx]*p>s[rx]*p)r=rx;
else l=lx;
}
for(int i=l;i<=r;i++)res=max(res,p*s[i]);
return res;
}
}t[N*4];
class seg_tree
{
public:
void modify(int x,int l,int r,int des)
{
if(des==r)t[x].build(l,r);
if(l==r)return;
int mid=l+r>>1,lc=x<<1,rc=lc+1;
if(des<=mid)modify(lc,l,mid,des);
else modify(rc,mid+1,r,des);
}
ll qry(int x,int l,int r,int ql,int qr,int a,int b)
{
if(ql<=l&&r<=qr)return t[x].qry(a,b);
int mid=l+r>>1,lc=x<<1,rc=lc+1;ll res=-inf;
if(ql<=mid)res=max(res,qry(lc,l,mid,ql,qr,a,b));
if(qr>mid)res=max(res,qry(rc,mid+1,r,ql,qr,a,b));
return res;
}
}T;
int get(int x)
{
return x^(la&0x7fffffff);
}
int main()
{
int x,y,l,r;char ch;
scanf("%d %c",&n,&ch);
m=n;flag=ch!='E';
while(m--)
{
scanf(" %c%d%d",&ch,&x,&y);
if(flag)x=get(x),y=get(y);
if(ch=='A')
{
po[++cnt]=(node){x,y};
T.modify(1,1,n,cnt);
}
else
{
scanf("%d%d",&l,&r);
if(flag)l=get(l),r=get(r);
printf("%lld\n",la=T.qry(1,1,n,l,r,x,y));
}
}
return 0;
}