http://acm.hdu.edu.cn/showproblem.php?pid=3183

A Magic Lamp

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8310    Accepted Submission(s): 3296

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
 
Source
 
Recommend
lcy   |   We have carefully selected several similar problems for you:  3188 3189 3184 3185 3186 
 
   思路主要是这样的: 因为需要你删除m个数使得结果最小,所以每次对字符串进行一次遍历,从前往后,只要a[i]>a[j] (j的位置为i后面未标记的第一个)  则对a[i]进行一次标记(赋赋值)将其除外,进行n次遍历,这样就删除了n个数字。因为删除的都是和后面比较相比下大的,所得结果当然就最小了。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <algorithm>
#include <iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include <stdio.h>
#include <string.h>
#include <vector>
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF  0x3f3f3f3f
using namespace std;
] ;
];
];
int main()
{
    int n , m ;
    while(~scanf("%s%d" , s , &m))
    {
        n = strlen(s);
        memset(a ,  , sizeof(a));
         ; i < n ; i++)
            a[i] = s[i] - ';
         ; i < m ; i++)//找到m个要删除的数
        {
             ; j < n ; j++)
            {
              //  if(a[j] > 0)//排除标记的
              //  {
                    int k ;
                     ; k < n ; k++)
                    {
                        )//排除标记的
                        break ;
                    }
                    if(a[j] > a[k])//找第一个开始递减的数
                    {
                        a[j] = - ;
                        break ;
                    }
              //  }
            }
        }
         , len =  ;
         ; i < n ; i++)
        {
            )//去前置零
                continue ;
            )
                continue ;
            b[len++] = a[i];
            )
                flag =  ;
        }
         ; i < len ; i++)
            printf("%d" , b[i]);
        )
            printf(");
        printf("\n");
    }
     ;
}

RMQ:

因为要找n-m个数,删除m个数。所以原数的第1位到m+1位的数字中最小的那位(假设是第i位)肯定是n-m位数的第一位。(想想为什么)

这样我们就找到了第一位a[i],接下来我们在从第i+1位数到m+2位数中找最小的那位,这个肯定是n-m位数的第二位。

以此类推,找够n-m位即可。

RMQ函数要做点修改。dmin[i][j]=k表示的是区间[i,i+(1<<j)-1]内最小值的下标而不是值了。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <algorithm>
#include <iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include <stdio.h>
#include <string.h>
#include <vector>
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF  0x3f3f3f3f
using namespace std;
] ;
];
] , dp[][];
int m , n ;

int Min(int x , int y)
{
    return s[x] <= s[y] ? x : y ;
}

void RMQ()
{
    memset(dp ,  , sizeof(dp));
      ; i < n ; i++)
        dp[i][] = i ;
     ; j <  ; j++)
    {
         ; i < n ; i++)
        {
             << j) -  < n)
            {
                dp[i][j] = Min(dp[i][j-] , dp[i+(<<j-)][j-]);
            }
        }
    }

}

int query(int l , int r)
{
    );
    <<k)+][k]);
}

vector<int>v;
int main()
{
    while(~scanf("%s%d" , s , &m))
    {
        v.clear();
        n = strlen(s);
        RMQ();
        m = n - m ;
         ;
        while(m--)
        {
            // 在 n - m 区间至少留一个数
            pos = query(pos , n - m - );//求的是最小值的下标
            v.push_back(pos);
            pos +=  ;
        }
         ;
         ; i < v.size() ; i++)
        {
            if(flag)
            {
                flag =  ;
                cout << s[v[i]];
            }
            ')
            {
                flag =  ;
                cout << s[v[i]] ;
            }
        }
        if(!flag)
            cout <<  ;
        cout <<endl ;
    }

     ;
}

RMQ(鸽巢原理或字符串操作)的更多相关文章

  1. hdu 3183 rmq+鸽巢原理

    题目大意: 给你一个数字字符串序列,给你要求删掉的数字个数m,删掉m个数使的剩下的数字字符串的之最小.并输出这个数字: 基本思路; 这题解法有很多,贪心,rmq都可以,这里选择rmq,因为很久没有写r ...

  2. [BZOJ4722]由乃[鸽巢原理+bitset+倍增]

    题意 给定长为 \(n\) 序列 \(a\) ,要求支持两种操作: \(1.\) 询问在一个区间 \([l,r]\) 中,是否能够选出两个交集为空的集合 $ \rm X ,Y$, 使得 \(\sum_ ...

  3. POJ2356 Find a multiple 抽屉原理(鸽巢原理)

    题意:给你N个数,从中取出任意个数的数 使得他们的和 是 N的倍数: 在鸽巢原理的介绍里面,有例题介绍:设a1,a2,a3,……am是正整数的序列,试证明至少存在正数k和l,1<=k<=l ...

  4. 51nod 1574 排列转换(贪心+鸽巢原理)

    题意:有两个长度为n的排列p和s.要求通过交换使得p变成s.交换 pi 和 pj 的代价是|i-j|.要求使用最少的代价让p变成s. 考虑两个数字pi和pj,假如交换他们能使得pi到目标的距离减少,p ...

  5. Two progressions(CodeForces-125D)【鸽巢原理】

    题意:将一列数划分为两个等差数列. 思路:首先,我要吹爆鸽巢原理!!!真的很强大的东西!!! 加入能完成题设操作,则前三个数中,必有至少两个数在同一序列,枚举三种情况(a1 a2,a2 a3,a1 a ...

  6. POJ 3370. Halloween treats 抽屉原理 / 鸽巢原理

    Halloween treats Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7644   Accepted: 2798 ...

  7. POJ 2356. Find a multiple 抽屉原理 / 鸽巢原理

    Find a multiple Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7192   Accepted: 3138   ...

  8. cf319.B. Modulo Sum(dp && 鸽巢原理 && 同余模)

    B. Modulo Sum time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  9. poj 2356 Find a multiple(鸽巢原理)

    Description The input contains N natural (i.e. positive integer) numbers ( N <= ). Each of that n ...

随机推荐

  1. file 显示文件的类型

    1. 命令功能 file命令是确定文件类型,也可以辨识一些文件的编码格式.通过文件的头部信息来获取文件类型.windows是通过扩展名来确定文件类型. 2. 语法格式 file  [option]  ...

  2. rabbit例子

    https://blog.csdn.net/csm201314/article/details/76377214 #include <SimpleAmqpClient/SimpleAmqpCli ...

  3. MYSQL中IN与EXISTS的区别

    在MYSQL的连表查询中,最好是遵循‘小表驱动大表的原则’ 一.IN与EXISTS的区别1.IN查询分析SELECT   *  FROM A WHERE id IN (SELECT id FROM B ...

  4. 前端每日实战:37# 视频演示如何把握好 transition 和 animation 的时序,创作描边按钮特效

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/mKdzZM 可交互视频教程 此视频 ...

  5. js如何判断用户使用的设备类型及平台

    前端开发经常遇到需要判断用户的浏览设备,是pc端还是移动端,移动端使用的是什么手机系统?android.ios.ipad.windows phone等等,有时候还需要知道用户浏览页面是在微信中打开还是 ...

  6. POJ 3784 Running Median (动态中位数)

    题目链接:http://poj.org/problem?id=3784 题目大意:依次输入n个数,每当输入奇数个数的时候,求出当前序列的中位数(排好序的中位数). 此题可用各种方法求解. 排序二叉树方 ...

  7. Windows 下搭建 SVN服务器

    目录 一 .安装Visual SVN 二.配置SVN 三.安装TortoiseSVN 四.上传项目到远程仓库 五.从远程仓库下载项目 六.检出项目 七.版本回退   参考链接 https://blog ...

  8. C#基础提升系列——C#任务和并行编程

    C#任务和并行编程 我们在处理有些需要等待的操作时,例如,文件读取.数据库或网络访问等,这些都需要一定的时间,我们可以使用多线程,不需要让用户一直等待这些任务的完成,就可以同时执行其他的一些操作.即使 ...

  9. linux运维、架构之路-linux用户管理

    一. linux系统用户分类 1.分类 ①超级用户:root,UID为0 ②普通用户:UID是500-65535的用户 ③虚拟用户:UID在1-499,一般不能登录,满足文件或服务启动的需要,/sbi ...

  10. FastDFS搭建文件管理系统

    参考:https://www.cnblogs.com/chiangchou/p/fastdfs.html 目录: 一:FastDFS介绍 1:简介: FastDFS 是一个开源的高性能分布式文件系统( ...