zoukankan      html  css  js  c++  java
  • RMQ hdu 3183 A Magic Lamp

    RMQ hdu 3183 A Magic Lamp
    //hdu 3183 A Magic Lamp
    //RMQ
    //用RMQ求剩下的n-m个数,第一个数肯定在第一个数和第m+1 个数之间的最小的那个数,
    //包括第一和m+1,第二个数肯定在上一次求的数到第m+2 个数之间,依次类推
    
    //注意:预处理log时,记得最大下标是所给数的长度,不是2的几次方,
    //下标就是多少。求最小数时,若有多个和最小值相等的数则去最左的那个,
    //要不然求下一个最小数时会忽略这些数
    
    #include <stdio.h>
    #include <string.h>
    //#include <math.h>
    
    #include <algorithm>
    
    using namespace std;
    
    #define comein freopen("in.txt", "r", stdin);
    #define comeout freopen("out.txt", "w", stdout);
    #define N 1005
    #define INF 1<<30
    #define eps 1e-5
    
    char num[N];
    int dp_min[20][N], pos[N];
    int lo_2[N];
    
    void RMQ(int len)
    {
        for(int i = 1; i <= len; ++i)
            dp_min[0][i] = i;
        int index = lo_2[len];
        for(int i = 1; i <= index; ++i)
        {
            for(int j = 1; j + (1<<i) - 1 <= len; ++j)
            {
                if(num[dp_min[i-1][j]] <= num[dp_min[i-1][j + (1<<(i-1)) ]])
                    dp_min[i][j] = dp_min[i-1][j];
                else
                    dp_min[i][j] = dp_min[i-1][j + (1<<(i-1)) ];
            }
        }
    }
    
    int get_min_pos(int from, int to)
    {
        int index = lo_2[to - from + 1];
        //若有多个和最小值相等的数则去最左的那个,所以这里要取等
        if(num[dp_min[index][from]] <= num[dp_min[index][to - (1<<index) + 1]])
            return dp_min[index][from];
        return dp_min[index][to - (1<<index) + 1];
    }
    
    int main()
    {
        lo_2[0] = -1;
    
        for(int i = 1; i < N; ++i)     //求2为底的对数
            lo_2[i] = i&(i-1) ? lo_2[i-1] : lo_2[i-1] + 1;
    
        while(scanf("%s", &num[1]) != EOF)
        {
            int del_n, len = strlen(&num[1]);
            RMQ(len);
    
            scanf("%d", &del_n);
            int left = len - del_n, from = 1, to;
            to = del_n + 1;
            while(left)
            {
                pos[left-1] = get_min_pos(from, to);
                from = pos[left-1] + 1;
                to++;
                left--;
            }
            left = len - del_n;
            sort(pos, pos + left);
            int i = 0;
            while(num[pos[i]] == '0' && i < left)
                i++;
            if(i == left)
            {
                puts("0");
                continue;
            }
            for(; i < left; ++i)
                putchar(num[ pos[i] ]);
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    [CSAPP笔记][第一章计算机系统漫游]
    [暂停学习几天]
    [汇编学习笔记][第十七章使用BIOS进行键盘输入和磁盘读写
    [汇编学习笔记][第十六章直接定址表]
    [汇编语言学习笔记][第十五章 外中断]
    [汇编学习笔记][第十四章 端口]
    [汇编学习笔记][第十三章int指令]
    [汇编学习笔记][第十二章内中断]
    [汇编学习笔记][第十一章标志寄存器]
    [汇编学习笔记][第十章 CALL和RET指令]
  • 原文地址:https://www.cnblogs.com/gabo/p/2606636.html
Copyright © 2011-2022 走看看