题外话:终于不再拖了啊...今天竟然有了友链...于是心情好就补了一篇[email protected][email protected]
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 }