传送门
题解:
其实这个写法二进制分组和ZKW线段树差别已经不大了。。。
直接建线段树,暴力insert,当一个区间满了的时候建立凸包即可,分上下两个凸壳来建。
询问直接在凸壳上二分即可。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define cs const
namespace IO{
cs int Rlen=1<<22|1;
char buf[Rlen],*p1,*p2;
inline char gc(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;}
inline char peek(){return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1;}
inline char ga(){while(!isalpha(peek()))++p1;return *p1++;}
template<typename T>
inline T get(){
char c;T num;bool f=0;
while(!isdigit(c=gc()))f=c=='-';num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return f?-num:num;
}
inline int gi(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
struct Point{int x,y;};
inline ll operator*(cs Point &a,cs Point &b){return (ll)a.x*b.y-(ll)a.y*b.x;}
inline ll dot(cs Point &a,cs Point &b){return (ll)a.x*b.x+(ll)a.y*b.y;}
inline Point operator-(cs Point &a,cs Point &b){return (Point){a.x-b.x,a.y-b.y};}
inline Point operator-(cs Point &a){return (Point){-a.x,-a.y};}
cs int N=4e5+7,mx=1<<19;
Point nd[2][20][N],*hull[mx+N][2],*a;
int siz[mx+N][2],now,tp,n,op;ll ans;
inline void ins(cs Point &p){
if(tp&&a[tp-1].x==p.x){
if(a[tp-1].y>=p.y)return ;
--tp;
}
while(tp>1&&(a[tp-2]-a[tp-1])*(p-a[tp-1])<=0)--tp;
a[tp++]=p;
}
inline void build(int p){
if(siz[p][0])return ;
for(int re t=0;t<2;++t){
a=hull[p][t],tp=0;
Point *Lx=hull[p<<1][t],*cs Ly=Lx+siz[p<<1][t];
Point *Rx=hull[p<<1|1][t],*cs Ry=Rx+siz[p<<1|1][t];
while(Lx<Ly&&Rx<Ry)ins(Lx->x<Rx->x?*Lx++:*Rx++);
while(Lx<Ly)ins(*Lx++);while(Rx<Ry)ins(*Rx++);
siz[p][t]=tp;
}
}
inline void push(){
int x=gi(),y=gi(),q=mx+(++now);
if(op)x^=ans,y^=ans;
siz[q][0]=1;*hull[q][0]=(Point){x,y};
siz[q][1]=1;*hull[q][1]=(Point){-x,-y};
for(;q&1;q>>=1,build(q));
}
inline ll query(int q,Point p){
int l=-1,r;
if(p.y>=0)a=hull[q][0],r=siz[q][0]-1;
else a=hull[q][1],p=-p,r=siz[q][1]-1;
while(l+1<r){
int mid=l+r>>1;
if(dot(a[mid],p)>=dot(a[mid+1],p))r=mid;
else l=mid;
}
return dot(a[r],p);
}
inline void query(){
int x,y,l,r;
if(op)x=gi()^ans,y=gi()^ans,l=(gi()^ans)+mx-1,r=(gi()^ans)+mx+1;
else x=gi(),y=gi(),l=gi()+mx-1,r=gi()+mx+1;
ans=-(1ll<<61);
Point p=(Point){x,y};
for(;l^r^1;l>>=1,r>>=1){
if(~l&1)ans=std::max(ans,query(l^1,p));
if(r&1) ans=std::max(ans,query(r^1,p));
}
cout<<ans<<"\n";ans&=0x7FFFFFFF;
}
signed main(){
#ifdef zxyoi
freopen("vector.in","r",stdin);
#endif
n=gi(),op=ga()!='E';
for(int re l=mx,r=mx+n+10,d=0;l;l>>=1,r>>=1,++d)
for(int re i=l;i<=r;++i)hull[i][0]=nd[0][d]+(i-l<<d),hull[i][1]=nd[1][d]+(i-l<<d);
for(int re t=mx;t;t>>=1)siz[t][0]=siz[t-1][0]=siz[t][1]=siz[t-1][1]=-1;
while(n--){
switch(ga()){
case 'A':push();break;
case 'Q':query();break;
}
}
return 0;
}