BZOJ 3533 [Sdoi2014]向量集
題外話:終於不再拖了啊...今天竟然有了友鏈...於是心情好就補了一篇...@_@
Description
維護一個向量集合,在線支持以下操作:
"A x y":加入向量(x,y);
"Q x y l r":詢問第L個到第R個加入的向量與向量(x,y)的點積的最大值。集合初始時為空。(|x|,|y| < =10^8,1 < =L < =R < =T,其中T為已經加入的向量個數)
Input
輸入的第一行包含整數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。
Output
對每個Q操作,輸出一個整數表示答案。
Sample Input
6 A
A 3 2
Q 1 5 1 1
A 15 14
A 12 9
Q 12 8 12 15
Q 21 18 19 18
Sample Output
13
17
17
解釋:解密之後的輸入為
6 E
A 3 2
Q 1 5 1 1
A 2 3
A 1 4
Q 1 5 1 2
Q 4 3 2 3
HINT
1 < =N < =4×10^5
這道題...課上講的第一道題(之前的第一題出了鍋...),也不難想,大概就是線段樹上靜態維護凸包(話說動態的話這個數據範圍是不是不可做?)。
首先是關於凸包(第一次寫凸包...這個時候...大概已經沒救了),比如讀入的向量是(a,b),我們要在第L個到第R個向量裏找到一個向量(x,y)使得ax*by最大。設最後答案是ans。
可以列出式子: ax+by=ans
兩邊同除 b (a/b)x+y=ans/b
然後移項 y=-(a/b)x+ans/b
這樣的話...比較顯然...-(a/b)是已知的斜率,那麽找ans最大的話,把b分情況討論一下,如果b>=0,那麽在y軸上的截距應該盡可能高,那麽維護一個上凸殼,在上凸殼上找三分答案;如果b<0,那麽在y軸上的截距應盡可能小,那麽就在維護的下凸殼上三分答案。
之後對於每次查詢的[l,r],用線段樹維護,每個節點維護所屬區間的上凸殼和下凸殼(把每個向量看成點),但是發現每次合並復雜度是O(區間長度),好像炸了...但是考慮每個葉子節點只會被修改一次,其他節點好像也可以?有一個很顯然的結論,對於每個詢問,一定不會去直接詢問一個還沒有覆蓋滿的區間節點。所以...就可以在這裏優化了,只有我把這個區間填滿的時候,才去合並他的兩個子區間(這個過程要求O(區間長度),因為凸包有序)。
一些細節:每個節點維護凸包...貌似用vector比較方便吧...但是傳參的時候記得加上&...
下面是代碼:
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<iostream> 5 #include<vector> 6 using namespace std; 7 struct point{ 8 long long x,y; 9 friend point operator -(const point &a,const point &b){ 10 point ret; 11 ret.x=a.x-b.x; 12 ret.y=a.y-b.y; 13 return ret; 14 } 15 friend long long operator *(const point &a,const point &b){ 16 long long ret=a.x*b.y-a.y*b.x; 17 return ret; 18 } 19 friend long long operator ^(const point &a,const point &b){ 20 long long ret=a.x*b.x+a.y*b.y; 21 return ret; 22 } 23 friend bool operator <(const point &a,const point &b){ 24 if(a.x==b.x) return a.y<b.y; 25 return a.x<b.x; 26 } 27 }in; 28 int decode(long long x,long long a){return x^(a&0x7fffffff);} 29 vector<point>shang[1600010],xia[1600010]; 30 long long ans=0ll; 31 char s[5],flg[5]; 32 int m,st,ed; 33 void merges(vector<point> &lson,vector<point> &rson,vector<point> &pos){ 34 unsigned i=0,j=0,all=0; 35 while(i!=lson.size()||j!=rson.size()){ 36 if(i==lson.size()) in=rson[j++]; 37 else if(j==rson.size()) in=lson[i++]; 38 else in=(lson[i]<rson[j])?lson[i++]:rson[j++]; 39 while(all>=2&&((pos[all-1]-pos[all-2])*(in-pos[all-2]))>=0) all--,pos.pop_back(); 40 all++,pos.push_back(in); 41 }return; 42 } 43 void mergex(vector<point> &lson,vector<point> &rson,vector<point> &pos){ 44 unsigned i=0,j=0,all=0; 45 while(i!=lson.size()||j!=rson.size()){ 46 if(i==lson.size()) in=rson[j++]; 47 else if(j==rson.size()) in=lson[i++]; 48 else in=(lson[i]<rson[j])?lson[i++]:rson[j++]; 49 while(all>=2&&((in-pos[all-2])*(pos[all-1]-pos[all-2]))>=0) all--,pos.pop_back(); 50 all++,pos.push_back(in); 51 }return; 52 } 53 void insert(int l,int r,int pos){ 54 if(l==r){ 55 shang[pos].push_back(in); 56 xia[pos].push_back(in); 57 return; 58 } 59 int mid=(l+r)/2,lson=pos*2,rson=pos*2+1; 60 if(m<=mid) insert(l,mid,lson); 61 else insert(mid+1,r,rson); 62 if(r==m) merges(shang[lson],shang[rson],shang[pos]),mergex(xia[lson],xia[rson],xia[pos]); 63 return; 64 } 65 void sanfen(vector<point> &pos){ 66 int i,l=0,r=pos.size()-1,lmid,rmid; 67 while(r-l>2){ 68 lmid=(l*2+r)/3,rmid=(l+r*2)/3; 69 if((pos[lmid]^in)>(pos[rmid]^in)) r=rmid; 70 else l=lmid; 71 } 72 for(i=l;i<=r;i++) ans=max(ans,(pos[i]^in)); 73 return; 74 } 75 void find(int l,int r,int pos){ 76 if(st<=l&&r<=ed){ 77 if(in.y>=0) sanfen(shang[pos]); 78 else sanfen(xia[pos]); 79 return; 80 } 81 int mid=(l+r)/2,lson=pos*2,rson=pos*2+1; 82 if(st<=mid) find(l,mid,lson); 83 if(mid<ed) find(mid+1,r,rson); 84 return; 85 } 86 int read(){ 87 int ret=0;bool flag=false;char c=getchar(); 88 while(c<‘0‘||‘9‘<c){if(c==‘-‘) flag=true;c=getchar();} 89 while(‘0‘<=c&&c<=‘9‘) ret=ret*10+c-‘0‘,c=getchar(); 90 return flag?-ret:ret; 91 } 92 int main() 93 { 94 int i,n,x,y; 95 n=read(); 96 scanf("%s",flg); 97 for(i=1;i<=n;i++){ 98 scanf("%s",s); 99 if(s[0]==‘A‘){ 100 x=read(),y=read(); 101 if(flg[0]!=‘E‘){x=decode(x,ans),y=decode(y,ans);} 102 in.x=x,in.y=y,m++; 103 insert(1,n,1); 104 } 105 else{ 106 x=read(),y=read(),st=read(),ed=read(); 107 if(flg[0]!=‘E‘){x=decode(x,ans),y=decode(y,ans),st=decode(st,ans),ed=decode(ed,ans);} 108 in.x=x,in.y=y;ans=-4611686014132420609ll; 109 find(1,n,1); 110 printf("%lld\n",ans); 111 } 112 } 113 return 0; 114 }
BZOJ 3533 [Sdoi2014]向量集