【HDU 3183】下标RMQ

本文探讨了一道算法题:如何通过删除指定数量的位数使一个十进制数最小化。作者提出了使用贪心策略结合RMQ(Range Minimum Query)算法来高效解决此问题的方法。通过实现双向链表和RMQ算法,文章详细阐述了如何选择并删除不必要的数字以达到最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.题目链接。题目大意:给定一个n位的十进制数,删去m位,让剩下的值最小。

2.这个题目显然贪心,开始想的是从前到后查找逆序删除,因为从高位删除是最优(此处没有证明。。。。),然后删除每一个元素之后,就继续对这个数组进行相同的操作,循环m次即可。涉及到元素的删除,我们可以下一个双向的链表来实现这个操作。但是仔细的想一下,因为删除的过程中,我们需要保持余下的元素相对位置不变,其实就是说挑选n-m个最小的元素。那么我们对每个元素分析,第一个元素所在的区间一定是[1,m](假设这里下表从1开始)。因为如果这个区间不选任何元素,那么一定是选不够的。这个就是鸽巢原理了吧,所以我们做m次RMQ,这里的RMQ是其实是在记录下标。

#include<bits/stdc++.h>
const int N = 1100;
#pragma warning(disable:4996)
int a[N];
int dp[N][20];
using namespace std;
void  RMQMinIndex(int n, int b[])
{
	for (int i = 0; i < n; i++)
		dp[i][0] = i;
	for (int j = 1; (1 << j) <= n; j++)
		for (int i = 0; i + (1 << j) - 1 < n; i++)
			dp[i][j] = b[dp[i][j - 1]] <= b[dp[i + (1 << (j - 1))][j - 1]] ? dp[i][j - 1] : dp[i + (1 << (j - 1))][j - 1];
}
int qMinIndex(int s, int v, int b[])
{
	int k = (int)(log(v - s + 1) / log(2));
	return b[dp[s][k]] <= b[dp[v - (1 << k) + 1][k]] ? dp[s][k] : dp[v - (1 << k) + 1][k];
}

char str[N];
int ans[N];
int m;
int main()
{
	while (~scanf("%s%d", &str, &m))
	{
		int n = strlen(str);
		for (int i = 0; i < n; i++)a[i] = str[i] - '0';
		RMQMinIndex(n, a);
		int t = 0, temp = 0;
		for (int i = m; i < n; i++)
		{
			t = qMinIndex(t, i, a);
			ans[temp++] = a[t++];
		}
		t = 0;
		while (t < temp&&ans[t] == 0)t++;
		if (t >= temp)printf("0\n");
		else
		{
			for (int i = t; i < temp; i++)printf("%d",ans[i]);
			printf("\n");
		}
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值