题意大概是动态维护一堆向量 每次求和一个给定向量的点积最大值
sol:
把点积的式子转化一下,可以转化成一个直线的形式
然后就发现题目求的其实是一堆直线的截距的最大
这东西动态维护一个凸包能解决
开个线段树即可
为了保证复杂度 只在节点满的时候建立凸包
没了。
#include <bits/stdc++.h> using namespace std; struct Node{ long long x,y; Node () {} Node(long long a,long long b){x=a,y=b;} long long operator *(const Node &a) const {return x*a.y-y*a.x;} long long operator ^(const Node &a) const{return x*a.x+y*a.y;} Node operator -(const Node &a)const {return Node(x-a.x,y-a.y);} bool operator <(const Node &a)const {return (x==a.x)?y<a.y:x<a.x;} }; vector <Node> Tree[1600010],v1[1600010],v2[1600010]; void Insert(int Now,Node qwq,int l,int r,int pos){ Tree[Now].push_back(qwq); if (pos==r){ sort(Tree[Now].begin(),Tree[Now].end()); int i; for (i=0;i<=r-l;i++){ while (v1[Now].size()>1&&((Tree[Now][i]-v1[Now][v1[Now].size()-1])*(v1[Now][v1[Now].size()-2]-v1[Now][v1[Now].size()-1]))>=0) v1[Now].pop_back(); v1[Now].push_back(Tree[Now][i]); while (v2[Now].size()>1&&((Tree[Now][i]-v2[Now][v2[Now].size()-1])*(v2[Now][v2[Now].size()-2]-v2[Now][v2[Now].size()-1]))<=0) v2[Now].pop_back(); v2[Now].push_back(Tree[Now][i]); } } if (l==r) return; int mid=(l+r)>>1; if (pos<=mid) Insert(Now<<1,qwq,l,mid,pos); else Insert(Now<<1|1,qwq,mid+1,r,pos); } long long query1(int L,int R,Node ned,int l,int r,int Now) { //cout<<l<<" "<<r<<endl; if(L<=l&&r<=R){ int LL=1,RR=v1[Now].size()-1,Mid,Ans = 0; //cout<<LL<<" "<<RR<<endl; while(LL<=RR){ Mid=(LL+RR)>>1; if((ned^v1[Now][Mid])>(ned^v1[Now][Mid-1]))Ans=Mid,LL=Mid+1; else RR=Mid-1; //cout<<LL<<" "<<RR<<endl; } return ned^v1[Now][Ans]; } int mid=(l+r)>>1; long long ans = -1ll << 62; if(L<=mid) ans=max(ans,query1(L,R,ned,l,mid,Now<<1)); if(R>mid) ans=max(ans,query1(L,R,ned,mid+1,r,Now<<1|1)); return ans; } long long query2(int L,int R,Node ned,int l,int r,int Now) { if(L<=l&&r<=R){ int LL=1,RR=v2[Now].size()-1,Mid,Ans = 0; while(LL<=RR){ Mid=(LL+RR)>>1; if((ned^v2[Now][Mid])>(ned^v2[Now][Mid-1])) Ans=Mid,LL=Mid+1; else RR=Mid-1; } return ned^v2[Now][Ans]; } int mid=(l+r)>>1; long long ans = -1ll << 62; if(L<=mid) ans=max(ans,query2(L,R,ned,l,mid,Now<<1)); if(R>mid) ans=max(ans,query2(L,R,ned,mid+1,r,Now<<1|1)); return ans; } int main(){ freopen("vector.in","r",stdin); freopen("vector.out","w",stdout); int opt,tot=0; long long lasans=0; int Q; scanf("%d",&Q); for (int i=1;i<=Q;i++){ Node a; scanf("%d%lld%lld",&opt,&a.x,&a.y); a.x^=lasans; a.y^=lasans; if (opt==1) Insert(1,a,1,Q,++tot); else{ int l,r; scanf("%d%d",&l,&r); l^=lasans; r^=lasans; if (a.y>0) lasans=query1(l,r,a,1,Q,1); else lasans=query2(l,r,a,1,Q,1); printf("%lld ",lasans); } } return 0; }