【蓝桥杯 第八大奇迹】

本文介绍了蓝桥杯竞赛中的一道题目,涉及Z族评选最奇特建筑的问题。随着建筑的变动和不同人视野的限制,评选第八大奇迹变得复杂。解题思路提到使用树状数组和权值线段树结合的方法来解决区间第K大问题,通过维护区间权值信息来确定每个人心中的第八大奇迹的奇特值。
摘要由CSDN通过智能技术生成

【蓝桥杯 第八大奇迹】

题目描述

在一条 R 河流域,繁衍着一个古老的名族 Z。
他们世代沿河而居,也在河边发展出了璀璨的文明。
Z 族在 R 河沿岸修建了很多建筑,最近,他们热衷攀比起来。
他们总是在比谁的建筑建得最奇特。
幸好 Z 族人对奇特的理解都差不多,他们很快给每栋建筑都打了分,这样评选谁最奇特就轻而易举了。
于是,根据分值,大家很快评出了最奇特的建筑,称为大奇迹。
后来他们又陆续评选了第二奇特、第二奇特、……、第七奇特的建筑,依次称为第二大奇迹、第三大奇迹、……、第七大奇迹。
最近,他们开始评选第八奇特的建筑,准备命名为第八大奇迹。
在评选中,他们遇到了一些问题。
首先,Z 族一直在发展,有的建筑被拆除又建了新的建筑,新建筑的奇特值和原建筑不一样,这使得评选不那么容易了。
其次,Z 族的每个人所生活的范围可能不一样,他们见过的建筑并不是所有的建筑,他们坚持他们自己所看到的第八奇特的建筑就是第八大奇迹。
Z 族首领最近很头疼这个问题,他害怕因为意见不一致导致 Z 族发生分歧。
他找到你,他想先了解一下,民众自己认为的奇迹是怎样的。
现在告诉在 R 河周边的建筑的变化情况,以及在变化过程中一些人的生活范围,请编程求出每个人认为的第八大奇迹的奇特值是多少。

解题思路

看到这道题,还是很眼熟的,记得以前应该是做过的,但是时间太久忘了,今天又来复习一下,这道题可以用树套树或者整体二分来做,今天就先写个树状数组讨权值线段树版本的,之后复习了整体二分再来写一篇整体二分的。
首先树状数组可以维护的是前缀和的信息,比如用来求区间和。权值线段树可以用来求关于全局第K大这种问题,当把这两个算法结合在以前的时候就可以求解区间第K大了。
注意树状数组上面的每个点都是一颗权值线段树,这颗线段树维护的是树状数组这个点代表的区间的所有权值。只是以前树状数组关于求1-R的区间信息的时候,答案是保存在i(i=i&-i)这一系列的点上的。现在一个区间的信息是保存在以i(i=i&-1)为根的一系列权值线段树上面的,把这些权值线段树上的所有信息统合在一起就可以知道整个区间的信息了。

比如,X[i]中存放了权值在[l,r]这个区间的所有线段树(1,R)的信息,Y[i]中存放了权值在[l,r]这个区间的所有线段树(1,L-1)的信息

那么如果Σ{sum[rs[X(i)]]}-Σ{sum[rs[Y(i)]]}>=k,那么我们可以直接去右边区间找,否则去左边区间
注:L,R是求解的具体区间,[l,r]是线段树中的权值区间。sum[g]表示以g为根的权值线段树下有多少个值。k是取区间第k大。

上代码

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 200050
int root[N],ls[N*40],rs[N*40],sum[N*40];
int X[N],Y[N];
int cnt=0,L,n;
void tr_change(int &g,int l,int r,int x,int v){
   
	if(!g)g=++cnt;
	if(l==r){
   
		sum[g]+=v;return;
	}
	int mid=l+r>>1;
	if(x<=mid){
   
		tr_change(ls[g],l,mid,x,v);
		sum[g]=sum[ls[g]]+sum[rs[g]];
	}else{
   
		tr_change(rs[g],mid+1,r,x,v);
		sum[g]=sum[ls[g]]+sum
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值