1. 程式人生 > >BZOJ 3533 [Sdoi2014]向量集

BZOJ 3533 [Sdoi2014]向量集

不可 san div 向量 三分 zoj long 一行 using

題外話:終於不再拖了啊...今天竟然有了友鏈...於是心情好就補了一篇...@_@

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]向量集