题目描述
维护一个向量集合,在线支持以下操作:
"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)的点积的最大值。
集合初始时为空
输入格式
输入的第一行包含整数N和字符s,分别表示操作数和数据类别;
接下来N行,每行一个操作,格式如上所述。
请注意s≠'E'时,输入中的所有整数都经过了加密。你可以使用以下程序
得到原始输入:
inline int decode (int x long long lastans) {
return x ^ (lastans & Ox7fffffff);
}
function decode
begin
其中x为程序读入的数,lastans为之前最后一次询问的答案。在第一次询问之前,lastans=0。
注:向量(x,y)和(z,W)的点积定义为xz+yw。
输出格式
对每个Q操作,输出一个整数表示答案。
提示
1 < =N < =4×10^5
新加数据一组..2015.315
-
题解
- 设当前向量为$(a,b)$集合中向量为$(x,y)$,设$z = ax+by$,有$y = - frac{a}{b} x + frac{z}{b}$
- 最优化$z$:
- 当$b>0$即求过集合$S$中的某个点且斜率为$ - frac{a}{b}$的直线$y$截距最大的为哪条,答案一定在上凸包上;
- 同理$b<0$时求截距最小的为哪条;
- $b==0$随便哪条查即可;
- 如果维护了区间$[L,R]$的凸包就可以在里面三分;
- 应该是可以用线段树套$splay$参照$bzoj2300$但是效率比较低;
- 考虑直接用线段树,由于标号是顺序更新,所以一段区间的最后一个点被加入后再求区间的凸包,查询线段树查询+三分;
- 实现上凸包的排序可以用归并,(然而并没有快TAT);
- O(n log^2 n )
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 #include<cmath> 7 #include<vector> 8 #include<stack> 9 #include<map> 10 #include<set> 11 #define Run(i,l,r) for(int i=l;i<=r;i++) 12 #define Don(i,l,r) for(int i=l;i>=r;i--) 13 #define ll long long 14 #define ld long double 15 #define mk make_pair 16 #define fir first 17 #define sec second 18 #define il inline 19 #define rg register 20 #define pb push_back 21 #define ls (k<<1) 22 #define rs (k<<1|1) 23 using namespace std; 24 const int N=400010; 25 const ll inf=1e18; 26 int n,cnt,sz[N<<2],L[2][N<<2],R[2][N<<2]; 27 ll ans=0; 28 struct poi{ 29 ll x,y; 30 poi(int _x=0,int _y=0):x(_x),y(_y){}; 31 poi operator-(const poi&A)const{return poi(x-A.x,y-A.y);} 32 bool operator <(const poi&A)const{return x==A.x?y<A.y:x<A.x;} 33 }con[19][N],Q,tmp[19][N],p[N]; 34 il char gc(){ 35 static char*p1,*p2,s[1000000]; 36 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 37 return(p1==p2)?EOF:*p1++; 38 } 39 il int rd(){ 40 int x=0,f=1; char c=gc(); 41 while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();} 42 while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc(); 43 return x*f; 44 } 45 il ll dot(poi A,poi B){return (ll)A.x*B.x+(ll)A.y*B.y;} 46 il ll crs(poi A,poi B){return (ll)A.x*B.y-(ll)A.y*B.x;} 47 il ll max(ll x,ll y){return x>y?x:y;} 48 il void build(int k,int d,int l,int r){ 49 int mid=(l+r)>>1,idl=l,idr=mid+1,id=l,top,lst; 50 for(;idl<=mid||idr<=r;){ 51 if(idr>r||(idl<=mid&&tmp[d+1][idl]<tmp[d+1][idr])) 52 tmp[d][id]=tmp[d+1][idl],id++,idl++; 53 else 54 tmp[d][id]=tmp[d+1][idr],id++,idr++; 55 } 56 con[d][L[0][k]=top=l]=tmp[d][l]; 57 for(rg int i=l+1;i<=r;++i){ 58 while(top>l&&crs(con[d][top]-con[d][top-1],tmp[d][i]-con[d][top])<=0)top--; 59 con[d][++top]=tmp[d][i]; 60 } 61 R[0][k]=L[1][k]=lst=top; 62 for(rg int i=r-1;i>=l;--i){ 63 while(top>lst&&crs(con[d][top]-con[d][top-1],tmp[d][i]-con[d][top])<=0)top--; 64 if(i!=l)con[d][++top]=tmp[d][i]; 65 } 66 R[1][k]=top; 67 } 68 il void ask(int k,int d,int typ){ 69 int l=L[typ][k],r=R[typ][k]; 70 while(r-l>=3){ 71 int mid=(r-l)/3,mid1=l+mid,mid2=r-mid; 72 if(dot(con[d][mid1],Q)<dot(con[d][mid2],Q))l=mid1; 73 else r=mid2; 74 } 75 for(rg int i=l;i<=r;++i)ans=max(ans,dot(con[d][i],Q)); 76 ans=max(ans,dot(con[d][L[0][k]],Q)); 77 } 78 il void update(int k,int d,int l,int r,int x){ 79 if(l==r){ 80 sz[k]=1; 81 L[0][k]=L[1][k]=R[0][k]=R[1][k]=x; 82 tmp[d][x]=con[d][x]=p[x]; 83 } 84 else{ 85 int mid=(l+r)>>1; 86 if(x<=mid)update(ls,d+1,l,mid,x); 87 else update(rs,d+1,mid+1,r,x); 88 sz[k]=sz[ls]+sz[rs]; 89 if(sz[k]==r-l+1)build(k,d,l,r); 90 } 91 } 92 il void query(int k,int d,int l,int r,int x,int y){ 93 if(l==x&&r==y){ask(k,d,Q.y>0);} 94 else{ 95 int mid=(l+r)>>1; 96 if(y<=mid)query(ls,d+1,l,mid,x,y); 97 else if(x>mid)query(rs,d+1,mid+1,r,x,y); 98 else query(ls,d+1,l,mid,x,mid),query(rs,d+1,mid+1,r,mid+1,y); 99 } 100 } 101 int main(){ 102 #ifndef ONLINE_JUDGE 103 freopen("bzoj3533.in","r",stdin); 104 freopen("bzoj3533.out","w",stdout); 105 #endif 106 char ch,tp;int x,y,l,r; 107 n=rd();tp=gc(); 108 while(!isalpha(tp))tp=gc(); 109 for(rg int i=1;i<=n;++i){ 110 ch=gc();while(!isalpha(ch))ch=gc(); 111 if(ch=='A'){ 112 x=rd();y=rd(); 113 if(tp!='E')x^=ans,y^=ans; 114 p[++cnt]=poi(x,y); 115 update(1,0,1,n,cnt); 116 }else{ 117 x=rd();y=rd();l=rd();r=rd(); 118 if(tp!='E')x^=ans,y^=ans,l^=ans,r^=ans; 119 Q=(poi){x,y}; 120 ans = -inf; 121 query(1,0,1,n,l,r); 122 printf("%lld ",ans); 123 ans &= 0x7fffffff; 124 } 125 } 126 return 0; 127 }//by tkys_Austin;