1. 程式人生 > >HDU 3183 A Magic Lamp【RMQ區間取數(貪心)】

HDU 3183 A Magic Lamp【RMQ區間取數(貪心)】

A Magic Lamp
題意:給出一個大數,然後給出N,輸出大數去除N個數之後的最小數,不輸出前導0;
思路:反向想一下就是從大數中取strlen(str)-N個數使取出的數最小,列舉每一個區間右端點,計算區間左端點即可,每次查詢需要得到查詢區間範圍內最小值的位置(多個最小值時反回位置最小者),所以d[][]儲存的應該是最小值的位置而不是最小值;

AC程式碼:

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int MAXN=1e3
+11; char str[MAXN]; int a[MAXN],ans[MAXN],d[MAXN][32]; void RMQ_init(int N) { for(int i=0;i<N;++i) d[i][0]=i; for(int j=1;(1<<j)<=N;++j) for(int i=0;i+(1<<j)-1<N;++i) { d[i][j]=a[d[i][j-1]]<=a[d[i+(1<<(j-1))][j-1]]?d[i][j-1]:d[i+(1<<(j-1))][j-1]; } } int
RMQ(int L,int R) { int k=0; while((1<<(k+1))<=R-L+1) ++k; return a[d[L][k]]<=a[d[R-(1<<k)+1][k]]?d[L][k]:d[R-(1<<k)+1][k]; } int main() { int N; while(~scanf("%s%d",str,&N)) { int len=strlen(str); for(int i=0;i<len;++i) a[i]=str[i]-'0'
; RMQ_init(len); int x=0,cnt=0; for(int i=N;i<len;++i) { x=RMQ(x,i); ans[cnt++]=a[x++]; } int i=0; while(i<cnt&&!ans[i]) ++i; if(i>=cnt) puts("0"); else { for(;i<cnt;++i) printf("%d",ans[i]); puts(""); } } return 0; }