HDU-3183——A Magic Lamp(RMQ问题+鸽巢原理)

来源:互联网 发布:软件程序 编辑:程序博客网 时间:2024/05/22 02:18

题意:给你一个共n位的数,让你删除其中的m个位,而且不改变原来数位的顺序,使得余下的数位组成的数最小!

分析:大多数人看到标题上的鸽巢原理肯定会疑惑,鸽巢原理是什么屌定理!然后仔细一看必然大失所望,原来鸽巢原理就是抽屉原理。其实这里是巧用了抽屉原理。

我们不妨反过来考虑,要删除m个位,就相当于要保留n-m个位使得组成的数最小,然后就是使得这个数第i(1,2,3,4,5,......)位最小,而且因为先后顺序不能改变(如果可以改变,那么这题就变成排序题了),那么我们先只能先考察第一个数位。我们显然发现第一个数位只能是在给定数位的第1个到第m+1个中的最小数位值的那个,不妨设取得的数位是第k个,那么第二个数位只能在给定数位的第k+1个到第m+2个之中,之后以此类推!最后把前置0去掉就AC了!

话说RMQ问题的ST算法真是好啊!

#include <map>#include <set>#include <stack>#include <cmath>#include <queue>#include <bitset>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstdlib>#include <sstream>#include <cstring>#include <iostream>#include <algorithm>#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;#define clr(x,y) memset(x,y,sizeof(x))#define maxn 1000+5#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define IT iteratortypedef long long ll;const double eps = 1e-9;const double pi  = acos(-1);const ll mod = 1e9+7; char str[maxn];char ans[maxn];int minn[maxn][10];int min(int i,int j){return str[i]<=str[j]?i:j;}void rmq(int n){clr(minn,0x3f3f3f3f);for(int i=0;i<n;i++)minn[i][0]=i;for(int j=1;j<10;j++)for(int i=0;i<n&&i+(1<<j)-1<n;i++)minn[i][j]=min(minn[i][j-1],minn[i+(1<<j-1)][j-1]);}int query(int l,int r){int k=(int)(log(r-l+1.0)/log(2.0));return min(minn[l][k],minn[r-(1<<k)+1][k]);}int main(){int m;while(~scanf("%s %d",str,&m)){int n=strlen(str);rmq(n);int ll=-1,M=m;int len=n-m;for(int i=0;i<len;i++,M++){ll=query(ll+1,M);ans[i]=str[ll];}int kk=0;while(ans[kk]=='0'&&kk<len)kk++;if(kk==len){puts("0");continue;}for(;kk<len;kk++)printf("%c",ans[kk]);puts("");}return 0;}


0 0