hdu 3183 A Magic Lamp RMQ ST 座標最小值

hdu 3183 A Magic Lamp RMQ ST 座標最小值

題目連接:http://acm.hdu.edu.cn/showproblem.php?pid=3183

題目大意:

從給定的串中挑出來m個數使得剩餘的數字最小,串的序列不能改變php

思路:

  • 將問題轉化爲求在n個數中挑選n-m個數,使之最小。假設最極端的狀況,全部最大的數字都在左側,佔據了m個位置,那麼咱們須要挑選的最小的數字的第一位就是在m+1位上。依次類推,第二位在m+2位上,最後一位也就在原串的最後一位上。反過來,假設最大的數字都在右側,佔了m個位置。那麼咱們須要挑選的最小數字的最後一位就是在n-m位上,倒數第二位在n-m-1位上,最終最後一位就是在第一位上。至此,能夠獲得咱們挑選最小數的第一位的取值範圍就是[1,m+1]。類比可得,第二位取值範圍[2,m+2],...。假設咱們此時已經求出了第一位所在的位置x,那麼第二位數字的範圍就能夠進一步縮小爲[x+1,m+2],依次咱們能夠求出所有的數字。同時要注意,ST表中保存的是該段區間最小值的下標。
  • ST在線 預處理O(nlogn) 查詢O(1) 運行時間:15ms
  • 這道題注意的細節有不少,寫了好久纔敢提交仍是WA了3發。/(ㄒoㄒ)/~~要注意題中說n不會大於串的長度是不成立的,要來特判

代碼:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
using namespace std;
const int maxn = 1005;
int minindex[maxn][10],data[maxn],res[maxn];
inline void init(int len) {
    for(int i=1; i<=len; ++i) minindex[i][0]=i;
    for(int j=1; j<=10; ++j) {
        for(int i=1; i<=len; ++i) {
            if((i+(1<<j)-1)<=len) {
                int t1=minindex[i][j-1],t2=minindex[i+(1<<(j-1))][j-1];
                if(data[t1]<=data[t2]) minindex[i][j]=t1;
                else minindex[i][j]=t2;
            }
        }
    }
}
inline int ask(int l, int r) {
    int k=31-__builtin_clz(r-l+1);
    int t1=minindex[l][k],t2=minindex[r-(1<<k)+1][k];
    if(data[t1]<=data[t2]) return t1;
    else return t2;
}
int main() {
    char s[1005];
    int n,len,l,r,ip1,ip2;
    while(~scanf("%s %d",s,&n)) {
        memset(minindex,0,sizeof(minindex));
        len=strlen(s);
        for(int i=0; i<len; ++i) {
            data[i+1]=s[i]-'0';
        }
        if(n>=len) {
            printf("0\n");
            continue;
        }
        init(len);
        len=len-n;
        l=1,r=n+1;
        ip2=1;
        for(int i=1; i<=len; ++i) {
            ip1=ask(l,r);
            res[ip2]=data[ip1];
            ++ip2;
            l=ip1+1;
            ++r;
        }
        ip2--;
        for(l=1; l<=ip2; ++l) {
            if(res[l]) break;
        }
        if(l>ip2) {
            printf("0\n");
            continue;
        }
        for(int i=l; i<=ip2; ++i) printf("%d",res[i]);
        printf("\n");
    }
    return 0;
}
相關文章
相關標籤/搜索