# BZOJ3533: [Sdoi2014]向量集

APIO张鑫同学跟我说的

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define ll long long
char c;
bool flag;
inline void read(ll &a){a=0;do c=getchar();while(c!='-'&&(c<'0'||c>'9'));c=c=='-'?flag=true,getchar():c;while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();a=(flag?flag=false,-a:a);}
const
double eps=1e-7;

struct P
{
ll x,y;
inline friend ll operator *(P a,P b){return a.x*b.y-a.y*b.x;}
P(){}
P(ll x,ll y):x(x),y(y){}
inline friend P operator -(P a,P b){return P(a.x-b.x,a.y-b.y);}
inline friend bool operator <(P a,P b){return a.x^b.x?a.x<b.x:a.y<b.y;}
}L[600001];
ll n;
inline bool cmp(ll a,ll b){return L[a]<L[b];}
ll stack[600001];
ll cache[600001];
struct Node
{
ll *rstack,*lstack;
ll rtop,ltop;
Node *lc,*rc;
ll l,r;
Node():lc(NULL),rc(NULL){}
Node(ll l,ll r,Node *lc,Node *rc):lc(lc),rc(rc),l(l),r(r){}
inline void bg()
{
ll i,top=0,n=0;
for(i=1;i<=rc->rtop;i++)
cache[++n]=rc->rstack[i-1];
for(i=1;i<=lc->rtop;i++)
cache[++n]=lc->rstack[i-1];
sort(cache+1,cache+1+n,cmp);
stack[1]=cache[1],stack[2]=cache[top=2];
for(ll i=3;i<=n;i++)
{
while(top>1&&(L[stack[top]]-L[stack[top-1]])*(L[cache[i]]-L[stack[top-1]])>=0)top--;
stack[++top]=cache[i];
}
rstack=new ll [rtop=top];
for(i=1;i<=top;i++)
rstack[i-1]=stack[i];
top=0,n=0;
for(i=1;i<=lc->ltop;i++)
cache[++n]=lc->lstack[i-1];
for(i=1;i<=rc->ltop;i++)
cache[++n]=rc->lstack[i-1];
sort(cache+1,cache+1+n,cmp);
stack[1]=cache[1],stack[2]=cache[top=2];
for(ll i=3;i<=n;i++)
{
while(top>1&&(L[stack[top]]-L[stack[top-1]])*(L[cache[i]]-L[stack[top-1]])<=0)top--;
stack[++top]=cache[i];
}
lstack=new ll [ltop=top];
for(ll i=1;i<=top;i++)
lstack[i-1]=stack[i];

}
inline void B(ll l)
{
lstack=new ll [rtop=ltop=1];
rstack=new ll [1];
lstack[0]=rstack[0]=l;
}
inline ll Query(ll x,ll y)
{
if(r-l==0)
return L[l].x*x+L[l].y*y;
if(r-l==1)return max(L[l].x*x+L[l].y*y,L[r].x*x+L[r].y*y);
if(y==0)
{
if(x<0)return L[lstack[0]].x*x;
return L[lstack[ltop-1]].x*x;
}
else    if(y>0)
{
ll mid,l=0,r=rtop-2;
while(l<r)
{
mid=(l+r>>1);
if((L[rstack[mid+1]].y-L[rstack[mid]].y)/(eps+L[rstack[mid+1]].x-L[rstack[mid]].x)>=-x/(eps+y))l=mid+1;
else r=mid;
}
return max(L[rstack[l]].x*x+L[rstack[l]].y*y,L[rstack[l+1]].x*x+L[rstack[l+1]].y*y);
}
else
{
ll mid,l=0,r=ltop-2;
while(l<r)
{
mid=(l+r>>1);
if((L[lstack[mid+1]].y-L[lstack[mid]].y)/(eps+L[lstack[mid+1]].x-L[lstack[mid]].x)<=-x/(eps+y))l=mid+1;
else r=mid;
}
return max(L[lstack[l]].x*x+L[lstack[l]].y*y,L[lstack[l+1]].x*x+L[lstack[l+1]].y*y);
}
}
};

inline ll Cg(ll &x,ll lastans) {
return x ^=(lastans & 0x7fffffff);
}

Node T[2000001];
const
ll INF=1ll<<61;
inline ll Max(ll&a,ll b){return a>b?a:a=b;}
ll Query(ll place,ll x,ll y,ll l,ll r)
{if(T[place].l>=l&&T[place].r<=r)return T[place].Query(x,y);ll a=-INF;ll lc=place<<1,rc=lc|1,mid=T[lc].r;if(mid>=l)Max(a,Query(lc,x,y,l,r));if(mid<r)Max(a,Query(rc,x,y,l,r));return a;}
void Modify(ll place,ll l)
{if(T[place].l==T[place].r)return T[place].B(l);int mid=T[place<<1].r;if(mid<l)Modify(place<<1|1,l);else Modify(place<<1,l);if(l==T[place].r)T[place].bg();}
ll C;
void Build(ll place,ll l,ll r)
{if(l^r)Build(place<<1,l,l+r>>1),Build(place<<1|1,(l+r>>1)+1,r);T[place]=Node(l,r,T+(place<<1),T+(place<<1|1));}
int main()
{
}