BZOJ 4311 向量

shallot+向量集 混合版?

首先我们考虑每个向量的存在时间为[L,R]

那么我们知道任意一个区间在线段树上最多被分解成logn个区间

那么我们可以像shallot一样进行区间覆盖

注意到本题的查询是在凸壳上完成的,而凸壳不像shallot的线性基一样有固定的时间复杂度

但是本题的查询是可分离的,那么我们不需要将向量下传,只需要在线段树的每一层做凸壳即可

查询时每走一层对该层三分取最优解,建造凸壳和三分方法同向量集

QAQ 上午因为排序不小心写反了符号调了好久 QAQ

时间复杂度O(nlog^2n)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<vector>
using namespace std;

typedef long long LL;
const int maxn=200010;
const LL oo=1LL<<62;
int n,m,f,x,cnt;
int top=0;
int L[maxn],R[maxn];
struct Point{
	int x,y;
	Point(int x=0,int y=0):x(x),y(y){}
	void print(){printf("%d %d\n",x,y);}
}p[maxn],st[4000010],now;
typedef Point Vector;
bool cmp(const Point &A,const Point &B){
	if(A.x==B.x)return A.y<B.y;
	return A.x<B.x;
}
Vector operator -(const Point &A,const Point &B){return Vector(A.x-B.x,A.y-B.y);}
LL Cross(const Point &A,const Point &B){return 1LL*A.x*B.y-1LL*A.y*B.x;}
LL Dot(const Point &A,const Point &B){return 1LL*A.x*B.x+1LL*A.y*B.y;}
struct ASK{
	int x,y,t;
}Q[maxn];
struct Seg_Tree{
	vector<Point>V;
	int A,B;
	void Get_Hull(){
		A=top+1;
		int sz=V.size();
		sort(V.begin(),V.end(),cmp);
		for(int i=0;i<sz;++i){
			while(top>A&&Cross(V[i]-st[top],st[top]-st[top-1])<=0)top--;
			st[++top]=V[i];
		}B=top;
	}
	LL Max(){
		if(V.empty())return 0;
		if(!A)Get_Hull();
		int L=A,R=B;
		LL ans=0;
		while(R-L>=3){
			int m1=(L+L+R)/3,m2=(L+R+R)/3;
			if(Dot(st[m1],now)<=Dot(st[m2],now))L=m1;
			else R=m2;
		}
		for(int i=L;i<=R;++i)ans=max(ans,Dot(st[i],now));
		return ans;
	}
}t[maxn<<2];
void read(int &num){
	num=0;char ch=getchar();
	while(ch<‘!‘)ch=getchar();
	while(ch>=‘0‘&&ch<=‘9‘)num=num*10+ch-‘0‘,ch=getchar();
}
void modify(int o,int L,int R,int x,int y,int id){
	if(L>=x&&R<=y){
		t[o].V.push_back(p[id]);
		return;
	}
	int mid=(L+R)>>1;
	if(y<=mid)modify(o<<1,L,mid,x,y,id);
	else if(x>mid)modify(o<<1|1,mid+1,R,x,y,id);
	else modify(o<<1,L,mid,x,y,id),modify(o<<1|1,mid+1,R,x,y,id);
}
LL ask(int o,int L,int R,int p){
	if(L==R)return t[o].Max();
	int mid=(L+R)>>1;
	if(p<=mid)return max(t[o].Max(),ask(o<<1,L,mid,p));
	else return max(t[o].Max(),ask(o<<1|1,mid+1,R,p));
}
int main(){
	read(n);
	for(int i=1;i<=n;++i){
		read(f);
		if(f==1){
			++cnt;
			read(p[cnt].x);read(p[cnt].y);
			L[cnt]=i;
		}else if(f==2){
			read(x);R[x]=i;
		}else{
			++m;
			read(Q[m].x);read(Q[m].y);
			Q[m].t=i;
		}
	}
	for(int i=1;i<=cnt;++i){
		if(!R[i])R[i]=n;
		modify(1,1,n,L[i],R[i],i);
	}
	for(int i=1;i<=m;++i){
		now=Point(Q[i].x,Q[i].y);
		printf("%lld\n",ask(1,1,n,Q[i].t));
	}
	return 0;
}

  

时间: 2024-07-31 21:27:13

BZOJ 4311 向量的相关文章

BZOJ 4311: 向量( 按时间分治 + 线段树 )

离线, 然后按时间分治, 每个向量都有出现时间[l, r], 直接插入时间线段树(一个向量只会影响O(logN)数量级的线段树节点). 在线段树每个节点弄出凸壳然后二分. 时间复杂度O(Nlog^2N) --------------------------------------------------------------------------- #include<cstdio> #include<cctype> #include<cstring> #includ

[BZOJ]3243 向量内积(Noi2016)

小C做了之后很有感觉的题目之一,但因为姿势不对调了很久. Description 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即: 现有 n 个d 维向量x1,...,xn ,小喵喵想知道是否存在两个向量的内积为k的倍数.请帮助她解决这个问题. Input 第一行包含3个正整数n,d,k,分别表示向量的个数,维数以及待检测的倍数.接下来n行每行有d个非负整数,其中第i行的第j个整数表示向量xi的第j维权值xi,j. N<=1

BZOJ 2299 向量(裴蜀定理)

题意:给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y). 实际上前四个向量能拼出(ma,nb)(m%2=n%2).后四个向量拼出(xb,ya)(x%2=y%2). 这样可以枚举这四个未知数在模二意义下的解.这两个向量相加为(ma+xb,nb+ya). 对于ma+xb=X.根据系数的奇偶性,如果有系数为奇数,可使得等式两边都减去一个数使得系数都为偶

bzoj 4004 向量拟阵

题解RT. eps = 1e-10 WrongAnswer eps = 1e-5 Accepted 1 /************************************************************** 2 Problem: 4004 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:516 ms 7 Memory:2844 kb 8 ***********************************

bzoj 2299 [HAOI2011]向量 裴蜀定理

bzoj 2299 [HAOI2011]向量 裴蜀定理 题意: 给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y). 限制: -2*1e9 <= a,b,x,y <= 2*1e9 思路: 题目的操作可以化为: 1. x +- 2a; 2. y +- 2a; 3. x +- 2b; 4. y +- 2b; 5. x + a && y

3243: [Noi2013]向量内积 - BZOJ

Description 两个d 维向量A=[a1,a2,...,ad]与B=[b1,b2,...,bd]的内积为其相对应维度的权值的乘积和,即: 现有 n 个d 维向量x1,...,xn ,小喵喵想知道是否存在两个向量的内积为k的倍数.请帮助她解决这个问题Input 第一行包含3个正整数n,d,k,分别表示向量的个数,维数以及待检测的倍数.接下来n行每行有d个非负整数,其中第i行的第j个整数表示向量xi的第j维权值xi,j.Output 包含两个整数,用空格隔开.如果存在两个向量xp,xq的内积

[BZOJ 2299][HAOI 2011]向量 题解(裴蜀定理)

[BZOJ 2299][HAOI 2011]向量 Description 给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y). 说明:这里的拼就是使得你选出的向量之和为(x,y) Input 第一行数组组数t,(t<=50000) 接下来t行每行四个整数a,b,x,y (-2109<=a,b,x,y<=2109) Output t行每行为Y

【BZOJ 2299】 2299: [HAOI2011]向量 (乱搞)

2299: [HAOI2011]向量 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1255  Solved: 575 Description 给你一对数a,b,你可以任意使用(a,b), (a,-b), (-a,b), (-a,-b), (b,a), (b,-a), (-b,a), (-b,-a)这些向量,问你能不能拼出另一个向量(x,y). 说明:这里的拼就是使得你选出的向量之和为(x,y) Input 第一行数组组数t,(t<=50000)

BZOJ 3533 sdoi 2014 向量集

设(x,y)为Q的查询点,分类讨论如下:1.y>0:  最大化a*x+b*y,维护一个上凸壳三分即可 2.y<0:最大化a*x+b*y  维护一个下凸壳三分即可 我们考虑对时间建出一棵线段树 对于每个区间,如果满了就做出两个凸壳 总时间复杂度是O(n*log^2n) 之后我们考虑查询,每个区间最多被分解为log(n)个区间 在每个区间的凸壳上三分最优解即可 至于优化,可以设定一个阈值,当区间长度小于阈值时不用做凸壳,查询时直接暴力就可以了 #include<cstdio> #inc