bzoj3533【SDOI2014】向量集

3533: [Sdoi2014]向量集

Time Limit: 25 Sec  Memory Limit: 512 MB

Submit: 669  Solved: 213

[Submit][Status][Discuss]

Description

维护一个向量集合,在线支持以下操作:

"A x y (|x|,|y| < =10^8)":加入向量(x,y);

" Q x y l r (|x|,|y| < =10^8,1 < =L < =R < =T,其中T为已经加入的向量个数)询问第L个到第R个加入的向量与向量(x,y)的点积的最大值。

集合初始时为空。

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

新加数据一组..2015.315

Source

Round 1 Day 2

线段树+凸包+三分,思路好题

有一个结论:答案一定会出现在凸包上,而且如果y>0则在上凸包上,否则在下凸包上。

具体证明我不太会…分享一个链接:http://blog.csdn.net/u012288458/article/details/50957363

然后在一个凸包上答案是单峰的,可以用三分来做。

于是问题就变成了如何动态维护区间的凸包,这个可以用线段树。

可是问题在于每次新加一个点会修改logn段区间,而凸包合并是O(n),显然这个复杂度不能接受。

有一个比较巧妙的解决方法,包含未插入位置的线段树节点一定不会被访问(这显然),所以每插入一个点x,只要将区间右端点是x的凸包合并就可以了。

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define maxn 400005
#define inf 1000000000000000000ll
using namespace std;
int n,tot;
ll ans;
struct P
{
	ll x,y;
	P(ll xx=0,ll yy=0){x=xx;y=yy;}
	friend P operator +(P a,P b){return P(a.x+b.x,a.y+b.y);}
	friend P operator -(P a,P b){return P(a.x-b.x,a.y-b.y);}
	friend ll operator *(P a,P b){return a.x*b.y-a.y*b.x;}
	friend ll operator ^(P a,P b){return a.x*b.x+a.y*b.y;}
	friend bool operator <(P a,P b){return a.x==b.x?a.y<b.y:a.x<b.x;}
};
vector<P> a[maxn*4],b[maxn*4];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline int decode(int x){return x^(ans&0x7fffffff);}
void merge_a(vector<P> &h1,vector<P> &h2,vector<P> &h)
{
	vector<P>::iterator i=h1.begin(),j=h2.begin();
	int top=0;P p;
	while (i!=h1.end()||j!=h2.end())
	{
		if (i==h1.end()) p=*(j++);
		else if (j==h2.end()) p=*(i++);
		else p=*i<*j?*(i++):*(j++);
		while (top>=2&&(h[top-1]-h[top-2])*(p-h[top-2])>=0) h.pop_back(),top--;
		h.push_back(p);top++;
	}
}
void merge_b(vector<P> &h1,vector<P> &h2,vector<P> &h)
{
	vector<P>::iterator i=h1.begin(),j=h2.begin();
	int top=0;P p;
	while (i!=h1.end()||j!=h2.end())
	{
		if (i==h1.end()) p=*(j++);
		else if (j==h2.end()) p=*(i++);
		else p=*i<*j?*(i++):*(j++);
		while (top>=2&&(h[top-1]-h[top-2])*(p-h[top-2])<=0) h.pop_back(),top--;
		h.push_back(p);top++;
	}
}
ll sanfen(vector<P> &h,P p)//这里不加& 会TLE
{
	int l=0,r=h.size()-1,lmid,rmid;
	while (r-l>2)
	{
		lmid=(l*2+r)/3;rmid=(l+r*2)/3;
		if ((h[lmid]^p)>(h[rmid]^p)) r=rmid;
		else l=lmid;
	}
	ll ret=-inf;
	F(i,l,r) ret=max(ret,(h[i]^p));
	return ret;
}
void insert(int k,int l,int r,int pos,P p)
{
	if (l==r)
	{
		a[k].push_back(p);
		b[k].push_back(p);
		return;
	}
	int mid=(l+r)>>1;
	if (pos<=mid) insert(k<<1,l,mid,pos,p);
	else insert(k<<1|1,mid+1,r,pos,p);
	if (r==pos)
	{
		merge_a(a[k<<1],a[k<<1|1],a[k]);
		merge_b(b[k<<1],b[k<<1|1],b[k]);
	}
}
ll query(int k,int l,int r,int L,int R,P p)
{
	if (l==L&&r==R) return p.y>0?sanfen(a[k],p):sanfen(b[k],p);
	int mid=(l+r)>>1;
	if (R<=mid) return query(k<<1,l,mid,L,R,p);
	if (L>mid) return query(k<<1|1,mid+1,r,L,R,p);
	return max(query(k<<1,l,mid,L,mid,p),query(k<<1|1,mid+1,r,mid+1,R,p));
}
int main()
{
	char flg[10],opt[10];
	n=read();scanf("%s",flg);
	F(i,1,n)
	{
		scanf("%s",opt);
		if (opt[0]=='A')
		{
			int x=read(),y=read();
			if (flg[0]!='E') x=decode(x),y=decode(y);
			insert(1,1,n,++tot,P(x,y));
		}
		else
		{
			int x=read(),y=read(),l=read(),r=read();
			if (flg[0]!='E') x=decode(x),y=decode(y),l=decode(l),r=decode(r);
			printf("%lld\n",ans=query(1,1,n,l,r,P(x,y)));
		}
	}
	return 0;
}
时间: 2024-10-12 12:49:58

bzoj3533【SDOI2014】向量集的相关文章

BZOJ3533 [Sdoi2014]向量集 【线段树 + 凸包 + 三分】

题目链接 BZOJ3533 题解 我们设询问的向量为\((x_0,y_0)\),参与乘积的向量为\((x,y)\) 则有 \[ \begin{aligned} ans &= x_0x + y_0y \y &= -\frac{x_0}{y_0}x + \frac{ans}{y_0} \\end{aligned} \] 所以向量集里的向量实际上可以对应到平面上一组点,我们用一个斜率固定的直线去经过这些点,使得斜率最大或最小 当\(y_0 > 0\)时,要求截距最大 当\(y_0 <

bzoj3533: [Sdoi2014]向量集

Description 维护一个向量集合,在线支持以下操作:"A x y (|x|,|y| < =10^8)":加入向量(x,y);" Q x y l r (|x|,|y| < =10^8,1 < =L < =R < =T,其中T为已经加入的向量个数)询问第L个到第R个加入的向量与向量(x,y)的点积的最大值.    集合初始时为空. Input 输入的第一行包含整数N和字符s,分别表示操作数和数据类别:    接下来N行,每行一个操作,格式如上

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

瞎题表

数据结构小练习bzoj3221:[Codechef FEB13] Obserbing the tree树上询问 树剖+主席树(区间修改,加等差数列)bzoj2735:世博会 主席树+切比雪夫距离转曼哈顿距离+我最弱的数学推理bzoj3217:ALOEXT 替罪羊套01Trie(我的码力还是弱得不行,傻逼错误一大堆……)精细的实现果然很重要(对于数据结构里的点(比如……),可以直接提取其维护的区间然后操作的啊)替罪羊的插入重建好像使得重建点的祖先的cover不正确了?然而并没有什么影响?(zyf提

YCB 的暑期计划

前言 YCB现在很弱(TAT) 暑假有一个月,赶快狂补一下. 大概的计划如下: 首先前期会以数据结构为主,毕竟代码能力太弱,涉及内容:线段树分治.二进制分组.KD-Tree. 等数据结构做到没有智商的时候加入一波数论,内容为 杜教筛.min_25筛. 然后中途小清新一下,做一些 组合博弈与构造题. 接着继续练代码能力,顺便学一些神奇的暴力:启发式合并.dsu on tree . 然后图论也忘的差不多了,就回过头去学点新东西,大概会有spfa判负环.0/1分数规划.差分约束. 估计这个时候也没有什

BZOJ 4311 向量

shallot+向量集 混合版? 首先我们考虑每个向量的存在时间为[L,R] 那么我们知道任意一个区间在线段树上最多被分解成logn个区间 那么我们可以像shallot一样进行区间覆盖 注意到本题的查询是在凸壳上完成的,而凸壳不像shallot的线性基一样有固定的时间复杂度 但是本题的查询是可分离的,那么我们不需要将向量下传,只需要在线段树的每一层做凸壳即可 查询时每走一层对该层三分取最优解,建造凸壳和三分方法同向量集 QAQ 上午因为排序不小心写反了符号调了好久 QAQ 时间复杂度O(nlog

洛谷 P3390 【模板】矩阵快速幂

这题的确是个模板 但也要提到有关矩乘的内容: 首先什么是矩阵? 给一个线性变换 F(x)   (她可能就是个函数,定义域为向量集) 她可以把一个N维向量变成M维 那么显然x的每一维都可能影响着F(x)的每一维,于是F(x)这个线性变换就应该是N*M个在每两维间的小映射构成的. 于是我们可以把她写成M行N列的矩阵(M行N列是出于习惯) 所以矩阵是用于形象的表示线性变换的工具: 所以怎么合乎习惯的构造矩阵呢? 举例说明: 如,有一个三元组(3维向量)x{a,b,c} 定义F(x)={a+b,b+c}

利用算法识别车厘子与樱桃

引言:朴素贝叶斯分类器作为基础的分类算法,早在基础数学时期就已经被使用,目前在各行各业中更是被广泛使用.近几年车厘子在中国地区卖得火热,面对车厘子和樱桃,很多老百姓很难分清楚,那么算法能帮我们区分吗? 本文选自<大数据时代的算法:机器学习.人工智能及其典型实例>. 车厘子是樱桃吗?它们有区别是什么呢?通过在水果市场采集,获得了一些关于车厘子和樱桃的相关特征数据.  通过现有的车厘子和樱桃的数据,在包含车厘子和樱桃的混合水果中,随机给一个车厘子或者樱桃,识别它是樱桃或者车厘子的可能性哪个大? 本

【甘道夫】用贝叶斯文本分类测试打过1329-3.patch的Mahout0.9 on Hadoop2.2.0

引言 接前一篇文章<[甘道夫]Mahout0.9 打patch使其支持 Hadoop2.2.0> http://blog.csdn.net/u010967382/article/details/39088035, 为Mahout0.9打过Patch编译成功后,使用贝叶斯文本分类来测试Mahout0.9对Hadoop2.2.0的兼容性. 欢迎转载,转载请注明出处: http://blog.csdn.net/u010967382/article/details/39088285 步骤一:将20ne