[蓝桥杯 2019 国 B] 第八大奇迹

题目传送:P8701 [蓝桥杯 2019 国 B] 第八大奇迹 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

思路:

第一:静态区间查询第八大第一个想法肯定是主席树,但是太麻烦了,这里略过不提。

第二:可以看到是固定只查询第八大,可以考虑线段树维护前八大即可。pushup用归并排序

代码:

using namespace std;
#include<iostream>

const int maxn=1e5+10;

struct node{
	int v[8]={0};
}t[maxn<<2];//每个节点记录这个区间的前八大 

inline void pushup(node & x,node & l,node & r)//用归并排序思想合并 
{
	int p1=0,p2=0,p=0;
	
	while(p<8&&p1<8&&p2<8)
		if(l.v[p1]>r.v[p2])x.v[p++]=l.v[p1++];
		else x.v[p++]=r.v[p2++];	
}

inline void modify(int x,int l,int r,int &dist ,int &v)
{
	if(l==r)
	{
		t[x].v[0]=v;
		return;
	}
	
	int mid=l+r>>1;
	
	if(mid>=dist)modify(x<<1,l,mid,dist,v);
	else modify(x<<1|1,mid+1,r,dist,v);
	
	pushup(t[x],t[x<<1],t[x<<1|1]);
}

inline node query(int x,int l,int r,int &L,int &R)
{
	if(l>=L&&r<=R)return t[x];
	
	int mid=l+r>>1;
	node t1,t2,ans;
	
	if(mid>=L)t1=query(x<<1,l,mid,L,R);
	if(mid<R)t2=query(x<<1|1,mid+1,r,L,R);
	
	pushup(ans,t1,t2);
	
	return ans;
}

int l,n,x,y;
char op;

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	
	cin>>l>>n;
	
	while(n--)
	{
		cin>>op>>x>>y;
		
		if(op=='C')modify(1,1,l,x,y);
		else cout<<query(1,1,l,x,y).v[7]<<'\n';
	}
	return 0;
}

题目要求找出一个整数 n,使得 n 的每一位数字都不小于其右边的任何一位数字,并且 n 是满足这个条件的数字中最大的一个。 解法1:从最高位开始,逐位确定每个数字的值。遍历数字 n,如果 n 的某一位数字小于其右边的数字,将该位数字减1,并将该位右边的所有数字都设置为 9。最后得到的就是满足条件的最大数字。 解法2:从最低位开始,逐位确定每个数字的值。初始化最大数字为 0,从最低位开始遍历,依次设置每个数字的值。对于第 i 位数字,要找到最大的满足条件的数字,只需要将该位数字从 0 至 9 中选取一个,使得选取的数字大于等于已经确定的最大数字的第 i 位数字。这样可以保证满足条件,并且得到最大的数字。 举例说明解法2:假设要找到一个满足条件的最大数字,位数为 5,计算过程如下: - 第 1 位数字可以选取的范围是 1-9,选取 9,确定第 1 位数字为 9。 - 第 2 位数字可以选取的范围是已确定的最大数字的第 2 位数字至 9,选取 9,确定第 2 位数字为 9。 - 第 3 位数字可以选取的范围是已确定的最大数字的第 3 位数字至 9,选取 9,确定第 3 位数字为 9。 - 第 4 位数字可以选取的范围是已确定的最大数字的第 4 位数字至 9,选取 9,确定第 4 位数字为 9。 - 第 5 位数字可以选取的范围是已确定的最大数字的第 5 位数字至 9,选取 9,确定第 5 位数字为 9。 最终得到的满足条件的最大数字为 99999。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DogDu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值