和2961求的是一个东西。
维护上下两个凸包,然后三分。
上次写得是一个正常的线段树,填满一个区间就合并。
这次写了一个奇怪的按二进制维护log棵类线段树状物的东西,然后发现跑得比线段树慢。。。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define N 810000
const ll inf=~0llu>>1;
int Q,l,r,top,cnt,n,num,xq,yq;
char opt[11],s[11];
ll ans;
int X[N],Y[N],p[N*20],ch[N][2];
int st[21],size[N],L[N],R[N],mx[N],mn[N];
int beg1[N],ed1[N],beg2[N],ed2[N];
ll getk(int p1,int p2,int p3)
{return (ll)(X[p2]-X[p1])*(Y[p3]-Y[p2])-(ll)(X[p3]-X[p2])*(Y[p2]-Y[p1]);}
void dec(int &x)
{
if(opt[1]=='E')return;
x=x^(ans& 0x7fffffff);
}
void ins1(int x,int v)
{
while(num-beg1[x]>=1&&getk(p[num-1],p[num],v)>=0)
num--;
p[++num]=v;
}
void ins2(int x,int v)
{
while(num-beg2[x]>=1&&getk(p[num-1],p[num],v)<=0)
num--;
p[++num]=v;
}
int merge(int x,int y)
{
int ret=++cnt,l1,l2;
ch[ret][0]=x;ch[ret][1]=y;
L[ret]=L[x];R[ret]=R[y];
mx[ret]=max(mx[x],mx[y]);
mn[ret]=min(mn[x],mn[y]);
size[ret]=size[x]+size[y];
beg1[cnt]=num+1;
l1=beg1[x],l2=beg1[y];
while(l1<=ed1[x]&&l2<=ed1[y])
{
int t1=p[l1],t2=p[l2];
if(X[t1]<X[t2]||(X[t1]==X[t2]&&Y[t1]<Y[t2]))
ins1(cnt,t1),l1++;
else ins1(cnt,t2),l2++;
}
while(l1<=ed1[x])
ins1(cnt,p[l1]),l1++;
while(l2<=ed1[y])
ins1(cnt,p[l2]),l2++;
ed1[cnt]=num;
beg2[cnt]=num+1;
l1=beg2[x],l2=beg2[y];
while(l1<=ed2[x]&&l2<=ed2[y])
{
int t1=p[l1],t2=p[l2];
if(X[t1]<X[t2]||(X[t1]==X[t2]&&Y[t1]>Y[t2]))
ins2(cnt,t1),l1++;
else ins2(cnt,t2),l2++;
}
while(l1<=ed2[x])
ins2(cnt,p[l1]),l1++;
while(l2<=ed2[y])
ins2(cnt,p[l2]),l2++;
ed2[cnt]=num;
return ret;
}
void newnode(int x,int y)
{
X[++n]=x;Y[n]=y;
st[++top]=++cnt;size[cnt]=1;
beg1[cnt]=ed1[cnt]=++num;p[num]=n;
beg2[cnt]=ed2[cnt]=++num;p[num]=n;
L[cnt]=R[cnt]=n;mx[cnt]=mn[cnt]=x;
while(top>1&&size[st[top]]==size[st[top-1]])
st[top-1]=merge(st[top-1],st[top]),top--;
}
ll getv(int x){return (ll)xq*X[x]+(ll)yq*Y[x];}
void proc(int x)
{
if(yq==0)
{
ans=max(ans,(ll)xq*mx[x]);
ans=max(ans,(ll)xq*mn[x]);
}
else
{
int l,r;
if(yq>0)l=beg1[x],r=ed1[x];
else l=beg2[x],r=ed2[x];
while(r-l>=5)
{
int lm=(l+l+r)/3,rm=(l+r+r)/3;
if(getv(p[lm])<getv(p[rm]))l=lm;
else r=rm;
}
for(int i=l;i<=r;i++)
ans=max(ans,getv(p[i]));
}
}
void query(int x)
{
if(!x||r<L[x]||l>R[x])return;
if(l<=L[x]&&R[x]<=r)
{proc(x);return;}
query(ch[x][0]);query(ch[x][1]);
}
int main()
{
//freopen("tt.in","r",stdin);
scanf("%d%s",&Q,opt+1);
for(int x,y;Q--;)
{
scanf("%s",s+1);
if(s[1]=='A')
{
scanf("%d%d",&x,&y);
dec(x);dec(y);
newnode(x,y);
}
else
{
scanf("%d%d%d%d",&x,&y,&l,&r);
dec(x);dec(y);dec(l);dec(r);
ans=-inf;xq=x;yq=y;
for(int i=1,t;i<=top;i++)
query(st[i]);
printf("%lld\n",ans);
}
}
return 0;
}