题解 P3309 【[SDOI2014]向量集】
不失一般性设当前询问的
于是我们维护这个凸壳.因为有区间询问所以线段树维护每个区间的凸壳.具体地,插入的时候统计当前区间已经有多少个点,如果点数等于当前区间长度那么构造出这个区间的凸壳.询问的时候拆成
求凸包这里使用按
插入的时候每个区间只会被构建一次凸包,总复杂度
查询的时候拆成
使用
这里当然还是用无脑的
这道题还告诉我们所有长成
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int N=2e6;
long long lastans;
struct Point{
int x,y;
bool operator <(const Point &a)const{return x!=a.x?x<a.x:y<a.y;}
Point operator -(const Point &a)const{return (Point){x-a.x,y-a.y};}
long long operator *(const Point &a)const{return 1ll*x*a.y-1ll*y*a.x;}
};
struct Node{vector<Point>st[2];}a[N];
int size[N],n;
char st[5];
long long calc(int rot,int x,int y)
{
int o=0;
if(y<0)x=-x,y=-y,o=1;
int l=0,r=a[rot].st[o].size()-1;
// cout<<rot<<" "<<l<<" "<<r<<endl;
while(l<r)
{
int mid=(l+r)>>1;//cout<<l<<" "<<r<<" "<<mid<<endl;
if(-1ll*x*(a[rot].st[o][mid+1].x-a[rot].st[o][mid].x)>=1ll*y*(a[rot].st[o][mid+1].y-a[rot].st[o][mid].y))r=mid;
else l=mid+1;
}
// cout<<l<<endl;
return 1ll*x*a[rot].st[o][l].x+1ll*y*a[rot].st[o][l].y;
}
long long query(int rot,int lt,int rt,int lq,int rq,int x,int y)
{
if(lt>=lq&&rt<=rq)return calc(rot,x,y);
int mid=(lt+rt)>>1;
if(rq<=mid)return query(rot<<1,lt,mid,lq,rq,x,y);
else if(lq>mid)return query(rot<<1|1,mid+1,rt,lq,rq,x,y);
else return max(query(rot<<1,lt,mid,lq,mid,x,y),query(rot<<1|1,mid+1,rt,mid+1,rq,x,y));
}
void build(int rot,int len)
{
for(int o=0;o<=1;o++)
{
vector<Point>tmp;tmp.clear();
vector<Point>::iterator i=a[rot<<1].st[o].begin(),j=a[rot<<1|1].st[o].begin();
for(;i!=a[rot<<1].st[o].end()||j!=a[rot<<1|1].st[o].end();)
if(i==a[rot<<1].st[o].end()||(j!=a[rot<<1|1].st[o].end()&&*j<*i))tmp.push_back(*j++);
else tmp.push_back(*i++);
int top=0;
for(vector<Point>::iterator i=tmp.begin();i!=tmp.end();++i)
{
while(top>1&&((a[rot].st[o][top-1]-a[rot].st[o][top-2])*(*i-a[rot].st[o][top-1]))>=0)--top,a[rot].st[o].pop_back();
a[rot].st[o].push_back(*i);++top;
}
}
}
void update(int rot,int lt,int rt,int q,int x,int y)
{
if(lt==rt){a[rot].st[0].push_back((Point){x,y}),a[rot].st[1].push_back((Point){-x,-y}),++size[rot];return;}
int mid=(lt+rt)>>1;
if(q<=mid)update(rot<<1,lt,mid,q,x,y);
else update(rot<<1|1,mid+1,rt,q,x,y);
++size[rot];if(size[rot]==rt-lt+1)build(rot,rt-lt+1);
}
void deco(int &x)
{
x^=(lastans&0x7fffffff);
}
void print(int rot,int lt,int rt)
{
printf("%d %d %d\n",rot,lt,rt);
int mid=(lt+rt)>>1;
if(lt!=rt)print(rot<<1,lt,mid),print(rot<<1|1,mid+1,rt);
}
int main()
{
int enc=0;
scanf("%d%s",&n,st+1);if(st[1]!='E')enc=1;
// cout<<enc<<endl;
// freopen("cswa.txt","w",stdout);
int nn=0;//print(1,1,n);
for(int i=1;i<=n;i++)
{
scanf("%s",st+1);
if(st[1]=='Q')
{
int l,r,x,y;
scanf("%d%d%d%d",&x,&y,&l,&r);
if(enc)deco(x),deco(y),deco(l),deco(r);
// cout<<x<<" "<<y<<" "<<l<<" "<<r<<endl;
printf("%lld\n",lastans=query(1,1,n,l,r,x,y));
}
else
{
int x,y;
scanf("%d%d",&x,&y);
if(enc)deco(x),deco(y);
// cout<<x<<" "<<y<<endl;
update(1,1,n,++nn,x,y);
}
// print(1,1,n);
}
}