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. java 中的引用类型

    GC基本原理 GC (Garbage Collection)的基本原理:将内存中不再被使用的对象进行回收,GC中用于回收的方法称为收集器,由于GC需要消耗一些资源和时间,Java在对对象的生命周期特征 ...

  2. vim插件YouCompleteMe安装

    这里在ubuntu16.4下安装的需要提前安装cmake clang python3sudo apt-get install clang  因为不能访问google,安装时,安装go的插件会访问goo ...

  3. vue修改Element的el-table样式

    修改Element中的el-table样式,可以使用以下几种方法: 1. row-style 行的 style 的回调方法,也可以使用一个固定的 Object 为所有行设置一样的 Style. 2. ...

  4. MongoDB的应用

    一.MongoDB后台管理 # ./mongo MongoDB shell version v3.4.2 connecting to: mongodb://127.0.0.1:27017 MongoD ...

  5. 23飞机大战__pygame 快速入门

      1. 使用 pygame 创建图形窗口 小节目标 游戏的初始化和退出 理解游戏中的坐标系 创建游戏主窗口 简单的游戏循环 可以将图片素材 绘制 到 游戏的窗口 上, 开发游戏之前需要先知道 如何建 ...

  6. RMQ Terminology

    原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11784644.html RMQ模型架构 RMQ Terminology Message 消息,消息是不 ...

  7. jenkins解决python不是内部命令

    1.在 Windows 提示符下运行是没有问题. 2.把Jenkins项目配置中 python main.py   修改成python可执行文件全路径:D:\Python35\python.exe m ...

  8. ubuntu 18.04下修改pip镜像源

    在home/用户名/目录下创建.pip文件夹 然后cd .pip 创建pip.conf文件touch pip.conf 输入以下内容然后保存即可 [global] timeout = 6000 ind ...

  9. [CSP-S模拟测试]:走格子(模拟+BFS+Dijkstra)

    题目描述 $CYJ$想找到他的小伙伴$FPJ$,$CYJ$和$FPJ$现在位于一个房间里,这个房间的布置可以看成一个$N$行$M$列的矩阵,矩阵内的每一个元素会是下列情况中的一种:$1.$障碍区域—这 ...

  10. 【Pytest】python单元测试框架pytest简介

    1.Pytest介绍 pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,但是比unittest框架使用起来更简洁,效率更高.根据pytest的官方网站介绍 ...