NOIP2023模拟7联测28 花之舞

这篇具有很好参考价值的文章主要介绍了NOIP2023模拟7联测28 花之舞。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目大意

有一个花园,每朵花可以表示为平面直角坐标系上的 N N N个点,第 i i i个点的坐标为 O ( x i , y i ) O(x_i,y_i) O(xi,yi)。定义两朵花之间的距离为它们的切比雪夫距离,即 d i s ( u , v ) = max ⁡ ( ∣ x u − x v ∣ , ∣ y u − y v ∣ ) dis(u,v)=\max(|x_u-x_v|,|y_u-y_v|) dis(u,v)=max(xuxv,yuyv)

q q q个询问,第 i i i个询问为一个区间 [ l i , r i ] [l_i,r_i] [li,ri],请确定一个 k ( l ≤ k ≤ r ) k(l\leq k\leq r) k(lkr),最大化 min ⁡ 1 ≤ u < v ≤ r , u ≠ k , v ≠ k d i s ( u , v ) \min\limits_{1\leq u<v\leq r,u\neq k,v\neq k}dis(u,v) 1u<vr,u=k,v=kmindis(u,v)。即,最大化:删掉一朵花后,区间里花之间距离最小值。

3 ≤ n ≤ 3 × 1 0 4 , 1 ≤ q ≤ 3 × 1 0 5 , 1 ≤ x i , y i ≤ 1 0 8 3\leq n\leq 3\times 10^4,1\leq q\leq 3\times 10^5,1\leq x_i,y_i\leq 10^8 3n3×104,1q3×105,1xi,yi108

1 ≤ l i < r i ≤ n , r i − l i ≥ 2 1\leq l_i<r_i\leq n,r_i-l_i\geq 2 1li<rin,rili2

保证不存在重合的点。

时间限制 4000 m s 4000ms 4000ms,空间限制 1024 M B 1024MB 1024MB


题解

显然,要最大化任意两点的最小值,最近点对的两个点必须删一个。那么,我们可以想办法求出所有在询问中可能用到的最近点对。

枚举 k k k 0 ≤ k ≤ log ⁡ v 0\leq k\leq \log v 0klogv,其中 v v v为值域),将平面直角坐标系分为大小为 2 k × 2 k 2^k\times 2^k 2k×2k的矩阵。对于每个 k k k,我们考虑求所有距离在 [ 2 k − 1 , 2 k ) [2^{k-1},2^k) [2k1,2k)上的点对(当然,求这个的目的是求出所有在询问中可能用到的最近点对,得到距离小于 2 k − 1 2^{k-1} 2k1的点对也无妨)。对于每个矩阵,找到相邻矩阵(相邻指共边或共顶点,也就是八连通)和自己的矩阵,对这九个矩阵分别进行操作。每次操作就是将这两个矩阵(自己和操作对象)的点按编号从小到大排序。这自己的矩阵为 A A A,操作对象的矩阵为 B B B,则对于 A A A中的每个点 x x x,在 B B B中找到最小的点 y y y y ≥ x y\geq x yx(注意 x , y x,y x,y是编号),将 z ∈ [ max ⁡ ( 0 , y − 8 ) , y − 1 ] z\in [\max(0,y-8),y-1] z[max(0,y8),y1]的点都存储在 x x x v e c t o r vector vector中,表示 x x x z z z可能在询问中构成最近点对。

为什么要取 z ∈ [ max ⁡ ( 0 , y − 8 ) , y − 1 ] z\in[\max(0,y-8),y-1] z[max(0,y8),y1]呢?因为如果 B B B中要取到 z ′ z' z,使得 z ′ < max ⁡ ( 0 , y − 8 ) z'<\max(0,y-8) z<max(0,y8) z ′ z' z x x x可能构成最近点对,则能让其构成最近点对的区间可定是包含 [ z ′ , x ] [z',x] [z,x]的。既然当前枚举的是距离在 [ 2 k − 1 , 2 k ) [2^{k-1},2^k) [2k1,2k)上的点对,则如果 B B B中存在 z ∈ [ max ⁡ ( 0 , y − 8 ) , y − 1 ] z\in [\max(0,y-8),y-1] z[max(0,y8),y1] z ′ z' z的距离小于 2 k − 1 2^{k-1} 2k1,则 z z z z ′ z' z的距离一定比 x x x z ′ z' z的距离小,也就是说只要询问包含 x x x z ′ z' z,则最近点对一定是 z z z z ′ z' z,也就是说 x x x z ′ z' z不可能在询问中构成最近点对。

我们发现,在最坏情况下,在 B B B中取 6 6 6个点之后,不管怎么加点,都会使得存在两个点的距离小于 2 k − 1 2^{k-1} 2k1。考虑到后面要删一个点,所以就取到 7 7 7 8 8 8为宜,所以上面取的区间为 [ max ⁡ ( 0 , y − 8 ) , y − 1 ] [\max(0,y-8),y-1] [max(0,y8),y1]。最后还要对每个点的 v e c t o r vector vector去重。

然后我们考虑询问怎么做。我们可以依照询问右边界升序扫描线,将可能的最近点对插入到线段树中。下面称上面处理出来的可能在询问中用到的最近点对为支配点对。

线段树的每个节点只考虑 左端点在节点对应的区间里 且 右端点不超过当前扫描到的边界 的支配点对,维护几个值,分别是:

  • 这些支配点对里,最近点对是哪对,距离是多少
  • 分别删掉上一条中最近点对中的一个点后的最近点对距离

合并区间的时候,设两边最近点对分别是 ( u 1 , v 1 ) (u_1,v_1) (u1,v1) ( u 2 , v 2 ) (u_2,v_2) (u2,v2),其中 u 1 < u 2 u_1<u_2 u1<u2。如果两边最近点对有共同端点,就可以将 删掉这个共同端点后的最近点对距离 更新为两边最小值;如果两边最近点对没有共同端点,那么一边的最近点对可能更新另一边的删掉某点后的最近点对距离。

询问时考虑删掉最近点对的哪个点,取最优即可。

时间复杂度为 O ( n log ⁡ n log ⁡ v + q log ⁡ n ) O(n\log n\log v+q\log n) O(nlognlogv+qlogn),其中 v v v x i , y i x_i,y_i xi,yi的值域。常数比较大,但时限有 5000 m s 5000ms 5000ms,是可以过的。文章来源地址https://www.toymoban.com/news/detail-740635.html

code

#include<bits/stdc++.h>
#define lc k<<1
#define rc k<<1|1
using namespace std;
const int N=30000,Q=300000,inf=2100000000;
int n,q,x[N+5],y[N+5],ans[Q+5];
vector<int>w[N+5];
vector<pair<int,int>>g[N+5];
map<pair<int,int>,vector<int>>mp;
struct node{
	int mn,x,y,v1,v2;
}tr[4*N+5];
int dis(int i,int j){
	return max(abs(x[i]-x[j]),abs(y[i]-y[j]));
}
void build(int k,int l,int r){
	tr[k]=(node){inf,-1,-1,inf,inf};
	if(l==r) return;
	int mid=l+r>>1;
	build(lc,l,mid);build(rc,mid+1,r);
}
node merge(node a,node b){
	node re;
	int v1,v2;
	if(a.mn<b.mn){
		v1=min(a.v1,b.mn);v2=a.v2;
		if(a.y==b.y) v2=min(v2,b.v2);
		else if(a.y==b.x) v2=min(v2,b.v1);
		else v2=min(v2,b.mn);
		re=(node){a.mn,a.x,a.y,v1,v2};
	}
	else{
		v1=b.v1;v2=b.v2;
		if(b.x==a.y) v1=min(v1,a.v2);
		else v1=min(v1,a.mn);
		if(b.y==a.y) v2=min(v2,a.v2);
		else v2=min(v2,a.mn);
		re=(node){b.mn,b.x,b.y,v1,v2};
	}
	return re;
}
void ch(int k,int l,int r,int x,int y){
	if(l==r&&l==x){
		int d=dis(x,y);
		if(d<tr[k].mn) tr[k]=(node){d,x,y,inf,tr[k].mn};
		else if(d<tr[k].v2) tr[k].v2=d;
		return;
	}
	int mid=l+r>>1;
	if(x<=mid) ch(lc,l,mid,x,y);
	else ch(rc,mid+1,r,x,y);
	tr[k]=merge(tr[lc],tr[rc]);
}
node find(int k,int l,int r,int x,int y){
	if(l>=x&&r<=y) return tr[k];
	int mid=l+r>>1;
	if(y<=mid) return find(lc,l,mid,x,y);
	if(x>mid) return find(rc,mid+1,r,x,y);
	return merge(find(lc,l,mid,x,y),find(rc,mid+1,r,x,y));
}
int main()
{
	freopen("flower.in","r",stdin);
	freopen("flower.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
	for(int dv=0;dv<=27;dv++){
		mp.clear();
		for(int i=1;i<=n;i++){
			mp[{x[i]>>dv,y[i]>>dv}].push_back(i);
		}
		for(auto pv:mp){
			const auto &p=pv.first;
			const auto &v=pv.second;
			for(int dx=-1;dx<=1;dx++){
				for(int dy=-1;dy<=1;dy++){
					auto it=mp.find({p.first+dx,p.second+dy});
					if(it==mp.end()) continue;
					const auto &v1=it->second;
					for(int i=0,j=0;i<v.size();i++){
						while(j<v1.size()&&v1[j]<v[i]) ++j;
						for(int k=max(0,j-8);k<j;k++){
							w[v[i]].push_back(v1[k]);
						}
					}
				}
			}
		}
	}
	for(int i=1;i<=n;i++){
		sort(w[i].begin(),w[i].end());
		w[i].erase(unique(w[i].begin(),w[i].end()),w[i].end());
	}
	scanf("%d",&q);
	for(int i=1,l,r;i<=q;i++){
		scanf("%d%d",&l,&r);
		g[r].push_back({l,i});
	}
	build(1,1,n);
	for(int i=1;i<=n;i++){
		for(auto l:w[i]) ch(1,1,n,l,i);
		for(auto k:g[i]){
			int l=k.first,id=k.second;
			node re=find(1,1,n,l,i);
			ans[id]=max(re.v1,re.v2);
		}
	}
	for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
	return 0;
}

到了这里,关于NOIP2023模拟7联测28 花之舞的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 线段树好题! P2824 [HEOI2016/TJOI2016]排序 题解

    题目传送门 线段树好题!!!! 咕咕了挺久的一道题目,很早之前就想写了,今天终于找了个时间A掉了。 给定一个 (1) 到 (n) 的排列,有 (m) 次操作,分两种类型。 1. 0 l r 表示将下标在 ([l, r]) 区间中的数升序排序。 2. 1 l r 表示将下标在 ([l, r]) 区间中的数降序排序。

    2023年04月09日
    浏览(34)
  • CSP模拟58联测20 回忆旅途的过往

    题目大意 有 n n n 个砝码,每个砝码的初始重量为 a i a_i a i ​ 。有 q q q 次操作,每次操作分为以下两种类型: 1 l r x :表示将 l l l 到 r r r 之间的所有 a i a_i a i ​ 都变成 x x x 2 l r x :查询 l l l 到 r r r 之间的所有砝码,每个砝码可以用无限次,求是否能称出质量 x x x a i a_

    2024年02月07日
    浏览(44)
  • 【华为OD机试 2023最新 】模拟商场优惠打折(C语言题解 100%)

    题目描述 模拟商场优惠打折,有三种优惠券可以用,满减券、打折券和无门槛券。 满减券:满100减10,满200减20,满300减30,满400减40,以此类推不限制使用; 打折券:固定折扣92折,且打折之后向下取整,每次购物只能用1次; 无门槛券:一张券减5元,没有使用限制。 每个

    2024年02月03日
    浏览(44)
  • 2023第十四届蓝桥杯模拟赛第二期个人题解(Java实现)

    2023第十四届蓝桥杯校内模拟赛第三期个人题解(Java实现) 蓝桥杯真题——单词分析(Java实现) 这篇文章为个人题解,假如我写的解法有误,欢迎大家在评论区指正👏👏!!!希望这篇文章对你有帮助❤❤ 请找到一个大于 2022 的最小数,这个数转换成二进制之后,最低的

    2023年04月23日
    浏览(131)
  • 模拟赛好题分享

    @ 目录 山茶花 100pts T1区间逆序对 60pts 100pts 区间操作固定套路,转化为前缀操作 dream 20pts 神奇分块 杭州:转化题意,正难则反 正难则反(或者对于这种有删边操作的题), 我们看成反向加边 看题:构造 坐飞机:斜率优化DP 抓颓 : 启发式合并 + stl大杂烩 讨厌的线段树 Foo Fighters

    2024年02月05日
    浏览(56)
  • P1077 [NOIP2012 普及组] 摆花 题解

    小明的花店新开张,为了吸引顾客,他想在花店的门口摆上一排花,共 m m m 盆。通过调查顾客的喜好,小明列出了顾客最喜欢的 n n n 种花,从 1 1 1 到 n n n 标号。为了在门口展出更多种花,规定第 i i i 种花不能超过 a i a_i a i ​ 盆,摆花时同一种花放在一起,且不同种类的花

    2024年02月08日
    浏览(45)
  • Bessie Come Home回家 NOIP题解

    Bessie Come Home 回家 (comehome.pas) 【问题描述】 现在是晚餐时间,而母牛们在外面分散的牧场中。农民约翰按响了电铃,所以她们开始向谷仓走去。你的工作是要指出哪只母牛会最先到达谷仓(在给出的测试数据中,总会有且只有一只最快的母牛)。在挤奶的时候(晚餐前),每只母牛都在

    2024年02月11日
    浏览(53)
  • P1967 [NOIP2013 提高组] 货车运输 题解

    原题地址 由于题目要求的是使两点之间的最小边权最大,所以可以构造最大生成树(最大生成树一定是最大瓶颈生成树,而瓶颈生成树上两点之间的路径,在原图中的所有路径中,最小边权仍然最大,即满足题目要求,详见 https://oi-wiki.org/graph/mst/#瓶颈生成树 ),答案为最大

    2024年04月08日
    浏览(39)
  • 【洛谷 P1097】[NOIP2007 提高组] 统计数字 题解(映射)

    注意 :数据可能存在加强。 某次科研调查时得到了 n n n 个自然数,每个数均不超过 1.5 × 1 0 9 1.5 times 10^9 1.5 × 1 0 9 。已知不相同的数不超过 1 0 4 10^4 1 0 4 个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。 共 n + 1 n+1 n + 1 行。 第一

    2024年02月09日
    浏览(47)
  • 【洛谷 P1003】[NOIP2011 提高组] 铺地毯 题解(数组+贪心算法)

    为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。一共有 n n n 张地毯,编号从 1 1 1 到 n n n 。现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上

    2023年04月24日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包