hdu 3183 rmq+鸽巢原理
题目大意:
给你一个数字字符串序列,给你要求删掉的数字个数m,删掉m个数使的剩下的数字字符串的之最小。并输出这个数字;
基本思路;
这题解法有很多,贪心,rmq都可以,这里选择rmq,因为很久没有写rmq的题目了,所以这里先来一发。
至于鸽巢原理,这应该是一个很显而易见的道理,自己去脑补吧。
代码如下:
#include<iostream> #include<cstdio> #include<string> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const int maxn = 10000+10; char s[maxn]; int a[maxn],rmq[maxn][20],ans[maxn]; int n,m; void RMQ_Init(){ for(int j=1;(1<<j)<=n;j++){ for(int i=1;i+(1<<j)-1<=n;i++){ if(a[rmq[i][j-1]]<=a[rmq[i+(1<<(j-1))][j-1]]){ rmq[i][j]=rmq[i][j-1]; }else{ rmq[i][j]=rmq[i+(1<<(j-1))][j-1]; } } } } int query(int l,int r){ int k=floor(log((r-l+1))/log(2.0)); int res; if(a[rmq[l][k]]<=a[rmq[r-(1<<k)+1][k]]){ res=rmq[l][k]; }else{ res=rmq[r-(1<<k)+1][k]; } return res; } int main(){ while(scanf("%s%d",s,&m)!=EOF){ n=strlen(s); for(int i=0;i<n;i++){ a[i+1]=s[i]-'0'; rmq[i+1][0]=i+1; } RMQ_Init(); int id=1; int pos=0; for(int i=m+1;i<=n;i++){ id=query(id,i); ans[pos++]=a[id++]; } int sign=inf; for(int i=0;i<pos;i++){ if(ans[i]!=0){ sign=i; break; } } if(sign==inf){ printf("0\n"); }else{ for(int i=sign;i<pos;i++){ printf("%d",ans[i]); } printf("\n"); } } return 0; }