HDU 3183 - A Magic Lamp - [RMQ][ST算法]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183
Problem Description
Kiki likes traveling. One day she finds a magic lamp, unfortunately the genie in the lamp is not so kind. Kiki must answer a question, and then the genie will realize one of her dreams.
The question is: give you an integer, you are allowed to delete exactly m digits. The left digits will form a new integer. You should make it minimum.
You are not allowed to change the order of the digits. Now can you help Kiki to realize her dream?
Input
There are several test cases.
Each test case will contain an integer you are given (which may at most contains 1000 digits.) and the integer m (if the integer contains n digits, m will not bigger then n). The given integer will not contain leading zero.
Output
For each case, output the minimum result you can get in one line.
If the result contains leading zero, ignore it.
Sample Input
178543 4
1000001 1
100001 2
12345 2
54321 2
Sample Output
13
1
0
123
321
题意:
给你一个 $n$ 位的数字,你要删除其中的 $m$ 位,使得剩下来的每一位组成一个新数字是最小的。
题解:
换句话说,就是要在 $n$ 位中选择 $k=n-m$ 位数字组成新数字,使其最小。
显然,新数字的最高位必须在 $[1,n-k+1]$ 内,否则后面的数字将不够用。因此我们可以按照贪心的策略在 $[1,n-k+1]$ 内寻找最小的数字作为最高位。
然后,就转变为一个子问题:去掉选定的最高位,以及其前面的所有数字,剩下来的一串数字里,寻找 $k-1$ 位数字组成最小新数字。
一般来说,线段树是区间查询最大值的一种非常优秀的解决方法。不过本题没有修改操作,用线段树比较浪费。本题适合使用解决RMQ问题的著名的ST算法。
ST算法是基于倍增思想的。对于一个给定的序列 $a[1 \sim n]$,它能够在 $O(n \log n)$ 的预处理后,以 $O(1)$ 的时间复杂度在线地给出任意区间的最值。
首先我们知道,对于序列 $a[1 \sim n]$,它的子区间数目是 $O(n^2)$ 的。根据倍增思想,我们在这 $O(n^2)$ 的状态空间内选择一些 $2$ 的整数次幂的位置作为关键位置。
假设 $f(i,j)$ 代表了区间 $[i,i+2^j-1]$ 的最大值,即以 $a[i]$ 为起始的 $2^j$ 个数的最大值。显然递推边界为:对于任意的 $i \in [1,n]$,有$f(i,0) = a[i]$。
接下来,在递推求 $f(i,j)$ 时,区间的长度是成倍增长的,即 $f(i,j) = \max[f(i,j-1),f(i+2^{j-1},j-1)]$。从这个递推式不难看出,只要我们从小到大枚举 $j$,且对于固定的 $j$ 枚举 $i$ 即可。
而当我们要求 $[l,r]$ 的最大值时,我们可以求得 $k = \log(r-l+1)$,显然从 $l$ 往后的 $2^k$ 个数和从$r$ 往前的 $2^k$ 个数能够完全覆盖 $[l,r]$,因此只需要返回 $f(l,k)$ 和 $f(r-2^k+1,k)$ 中的较大值即可。
以下为求解RMQ问题的ST算法模板:
namespace ST
{
int n;
int f[maxn][(int)log2(maxn)+];
void init(int _n,int* a)
{
n=_n;
for(int i=;i<=n;i++) f[i][]=a[i];
for(int j=;(<<j)<=n;j++)
for(int i=;i<=n-(<<j)+;i++)
f[i][j]=max(f[i][j-],f[i+(<<(j-))][j-]);
}
int query(int l,int r)
{
int k=log2(r-l+);
return max(f[l][k],f[r-(<<k)+][k]);
}
}
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int maxn=; int n,m,k;
char num[maxn];
queue<int> q; namespace ST
{
int n;
pii f[maxn][(int)log2(maxn)+]; //first存储最小值,second存储最小值位置
pii min(const pii& a,const pii& b)
{
if(a.first==b.first)
return a.second<b.second?a:b;
else
return a.first<b.first?a:b;
}
void init(int _n,char* a)
{
n=_n;
for(int i=;i<=n;i++) f[i][]=make_pair(a[i]-'',i);
for(int j=;(<<j)<=n;j++)
for(int i=;i<=n-(<<j)+;i++)
f[i][j]=min(f[i][j-],f[i+(<<(j-))][j-]);
}
pii query(int l,int r)
{
int k=log2(r-l+);
return min(f[l][k],f[r-(<<k)+][k]);
}
} void solve(queue<int>& q,int l,int r,int k)
{
if(k==) return;
pii x=ST::query(l,r-k+);
q.push(x.first);
solve(q,x.second+,r,k-);
}
int main()
{
while(scanf("%s%d",num+,&m)!=EOF)
{
n=strlen(num+), k=n-m;
ST::init(n,num);
solve(q,,n,k);
while(!q.empty())
{
if(q.front()==) q.pop();
else break;
}
if(q.empty()) q.push();
while(!q.empty())
{
printf("%d",q.front());
q.pop();
}
printf("\n");
}
}
HDU 3183 - A Magic Lamp - [RMQ][ST算法]的更多相关文章
- hdu 3183 A Magic Lamp RMQ ST 坐标最小值
hdu 3183 A Magic Lamp RMQ ST 坐标最小值 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3183 题目大意: 从给定的串中挑 ...
- hdu 3183 A Magic Lamp(RMQ)
题目链接:hdu 3183 A Magic Lamp 题目大意:给定一个字符串,然后最多删除K个.使得剩下的组成的数值最小. 解题思路:问题等价与取N-M个数.每次取的时候保证后面能取的个数足够,而且 ...
- HDU 3183 A Magic Lamp(RMQ问题, ST算法)
原题目 A Magic Lamp Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu 3183 A Magic Lamp rmq或者暴力
A Magic Lamp Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Pro ...
- hdu 3183 A Magic Lamp(RMQ)
A Magic Lamp Time Limi ...
- HDU 3183 A Magic Lamp(二维RMQ)
第一种做法是贪心做法,只要前面的数比后面的大就把他删掉,这种做法是正确的,也比较好理解,这里就不说了,我比较想说一下ST算法,RMQ的应用 主要是返回数组的下标,RMQ要改成<=(这里是个坑点, ...
- hdu 3183 A Magic Lamp 【RMQ】
<题目链接> <转载于 >>> > 题目大意: 给出一个长度不超过1000位的数,求删去m位数字以后形成的最小的数字是多少. 解题分析: 分析:我们可以把题 ...
- hdu 3183 A Magic Lamp(给一个n位的数,从中删去m个数字,使得剩下的数字组成的数最小(顺序不能变),然后输出)
1.题目大意是,给你一个1000位的数,要你删掉m个为,求结果最小数. 思路:在n个位里面删除m个位.也就是找出n-m个位组成最小数 所以在区间 [0, m]里面找最小的数.相应的下标标号i 接着找区 ...
- hdu 3183 A Magic Lamp 贪心
#include <stdio.h> #include <string.h> #include <iostream> #include <algorithm& ...
随机推荐
- 腾讯企业邮箱设置发送邮件的配置(针对smtp)
QQ邮箱也是如下配置,不过需要进行开启smtp
- mysql常用的一些修改命令
修改表字段名称: alter table table_name change column column_name_old column_name_new column_type; mysql注释 ...
- echarts 通过dom获取echarts实例,批量监听reset
重点在于 echarts.getInstanceByDom 这个 API 我的js: // 懒加载优化:滚动节流策略 var __SCROLLTIMER__ = null // 重新设置 echart ...
- unity中的透视投影矩阵
一,unity中的Matrix4x4 例如一个矩阵的数据是: 0.9758,0,0,0,0,1.73205,0,0,0,0,-2.25,-16.25,0,0,-1,0 则实际矩阵是: M= m00 m ...
- slf4j-api、slf4j-log4j12、log4j之间关系
1. slf4j-api slf4j:Simple Logging Facade for Java,为java提供的简单日志Facade.Facade门面,更底层一点说就是接口.它允许用户以自己的喜好 ...
- ElasticStack系列之九 & master、data 和 client 节点
在生产环境下,如果不修改elasticsearch节点的角色信息,在高数据量,高并发的场景下集群容易出现脑裂等问题. 默认情况下,elasticsearch 集群中每个节点都有成为主节点的资格,也都存 ...
- 【30集iCore3_ADP出厂源代码(ARM部分)讲解视频】30-13 emWin底层驱动接口介绍
视频简介:该视频介绍emWin底层驱动接口. 源视频包下载地址:链接:http://pan.baidu.com/s/1nvPpC2d 密码:cbb7 银杏科技优酷视频发布区:http://i.youk ...
- 面向对象方法的重载(overloading)和覆盖(overriding)。
在有些JAVA书籍中将overriding称为重载,overloading称为过载. Overloading在一个类中可以定义多个同名方法,各个方法的参数表一定不同.但修饰词可能相同,返回值也可能 ...
- 安卓开发笔记——丰富多彩的TextView
随手笔记,记录一些东西~ 记得之前写过一篇文章<安卓开发笔记——个性化TextView(新浪微博)>:http://www.cnblogs.com/lichenwei/p/4411607. ...
- 【QT】对话框打开图像并用QPixmap显示
绘图设备是指继承QPaintDevice的子类,可以使用QPainter直接在其上面绘制图形,Qt一共提供了四个这样继承QPaintDevice的绘图设备类. 分别是QPixmap.QBitmap.Q ...