码迷,mamicode.com
首页 > 其他好文 > 详细

[BZOJ3533]向量集

时间:2017-12-07 20:48:39      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:维护   tor   pac   def   区间   而不是   div   title   16px   

首先,答案在凸包上为啥?去问ypl

然后点积结果是单峰的所以我们可以用三分查找(为了三分方便,我们要分别维护上下凸壳而不是极角序凸包)

查询区间,所以用线段树维护

动态维护要用高端数据结构,不方便三分,所以我们可以稍微延迟一点

具体点:因为此题的查询有特殊性质,即右端点不会大于当前已加入的数量,所以每当当前加入点到达了某些线段树节点的区间右端点才把整个区间的凸包建好(这样建凸包可以用数组存,方便三分)

#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
struct point{
	int x,y;
	point(int a=0,int b=0){
		x=a;
		y=b;
	}
}p[400010],stack[400010];
ll operator*(point&a,point&b){
	return a.x*(ll)b.x+a.y*(ll)b.y;
}
ll operator/(point a,point b){
	return a.x*(ll)b.y-a.y*(ll)b.x;
}
point operator-(point&a,point&b){
	return point(a.x-b.x,a.y-b.y);
}
typedef vector<point> vp;
vp up[1600010],down[1600010];
ll lastans;
int l[400010],r[400010],top;
bool op[400010];
void decode(int&x){
	x^=lastans&0x7fffffff;
}
bool cmp1(point a,point b){
	if(a.x==b.x)return a.y<b.y;
	return a.x<b.x;
}
void getup(vp&v){
	if(v.size()==0)return;
	sort(v.begin(),v.end(),cmp1);
	top=1;
	stack[0]=v[0];
	int i;
	for(i=1;i<v.size();i++){
		while(top>1&&(stack[top-1]-stack[top-2])/(v[i]-stack[top-1])>=0)top--;
		stack[top]=v[i];
		top++;
	}
	v.clear();
	for(i=0;i<top;i++)v.push_back(stack[i]);
}
bool cmp2(point a,point b){
	if(a.x==b.x)return a.y>b.y;
	return a.x<b.x;
}
void getdown(vp&v){
	if(v.size()==0)return;
	sort(v.begin(),v.end(),cmp2);
	top=1;
	stack[0]=v[0];
	int i;
	for(i=1;i<v.size();i++){
		while(top>1&&(stack[top-1]-stack[top-2])/(v[i]-stack[top-1])<=0)top--;
		stack[top]=v[i];
		top++;
	}
	v.clear();
	for(i=0;i<top;i++)v.push_back(stack[i]);
}
void modify(int pos,point&p,int l,int r,int x){
	up[x].push_back(p);
	down[x].push_back(p);
	if(pos==r){
		getup(up[x]);
		getdown(down[x]);
	}
	if(l==r)return;
	int mid=(l+r)>>1;
	if(pos<=mid)
		modify(pos,p,l,mid,x<<1);
	else
		modify(pos,p,mid+1,r,x<<1|1);
}
ll solve(int x,point&p){
	int i,l,r,m1,m2;
	ll ans=-9223372036854775807ll;
	if(p.y>0){
		l=0;
		r=up[x].size()-1;
		while(r-l>2){
			m1=((l<<1)+r)/3;
			m2=(l+(r<<1))/3;
			if(up[x][m1]*p<up[x][m2]*p)
				l=m1;
			else
				r=m2;
		}
		for(i=l;i<=r;i++)ans=max(ans,up[x][i]*p);
	}else{
		l=0;
		r=down[x].size()-1;
		while(r-l>2){
			m1=((l<<1)+r)/3;
			m2=(l+(r<<1))/3;
			if(down[x][m1]*p<down[x][m2]*p)
				l=m1;
			else
				r=m2;
		}
		for(i=l;i<=r;i++)ans=max(ans,down[x][i]*p);
	}
	return ans;
}
ll query(int L,int R,point&p,int l,int r,int x){
	if(L<=l&&r<=R)return solve(x,p);
	int mid=(l+r)>>1;
	ll ans=-9223372036854775807ll;
	if(L<=mid)ans=max(ans,query(L,R,p,l,mid,x<<1));
	if(mid<R)ans=max(ans,query(L,R,p,mid+1,r,x<<1|1));
	return ans;
}
int main(){
	int n,m,i,now;
	char s[5];
	bool sec=0;
	scanf("%d%s",&m,s);
	if(s[0]!=‘E‘)sec=1;
	n=0;
	for(i=1;i<=m;i++){
		scanf("%s%d%d",s,&p[i].x,&p[i].y);
		op[i]=s[0]==‘A‘;
		if(op[i])
			n++;
		else
			scanf("%d%d",l+i,r+i);
	}
	now=0;
	for(i=1;i<=m;i++){
		if(sec){
			decode(p[i].x);
			decode(p[i].y);
		}
		if(op[i]){
			now++;
			modify(now,p[i],1,n,1);
		}else{
			if(sec){
				decode(l[i]);
				decode(r[i]);
			}
			printf("%lld\n",lastans=query(l[i],r[i],p[i],1,n,1));
		}
	}
}

[BZOJ3533]向量集

标签:维护   tor   pac   def   区间   而不是   div   title   16px   

原文地址:http://www.cnblogs.com/jefflyy/p/8000464.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!