分析:
1、贪心,对数组进行扫描,如果a[i]>a[i+1]则把a[i]删除,直到删除m个为止;如果扫描一遍后删除的数不够m个,则在把数组末尾的数删除,直到总的删够m个,数组中剩下的数从头到尾即为结果。
2、RMQ算法解决,假设数组的长度为len,要删除的数的个数为m,那么最终数组中将剩下len-m个,因此可以找出数组中第一个到第m+1个的最小数作为最终结果的第一位,并假设最小数下标为i,再找出第i+1个到第m+2个的最小数作为最终结果的第二位,下标为j,再从第j+1个到m+3个找第三个,以此类推,找完即可。
#include<iostream>
using namespace std;
int dp[1010][33];
char num[1010];
char res[1010];
void GetRMQ(int n) //注意dp数组中保存的是下标
{
int i,j;
for(i=0;i<=n;i++)
dp[i][0]=i;
for(j=1;(1<<j)<=n;j++)
for(i=0;i+(1<<j)-1<n;i++)
dp[i][j]=num[dp[i][j-1]]<=num[dp[i+(1<<(j-1))][j-1]]?dp[i][j-1]:dp[i+(1<<(j-1))][j-1];
}
int Query(int l,int r)
{
int k=0;
while(1<<(k+1)<=r-l+1) k++;
return num[dp[l][k]]<=num[dp[r-(1<<k)+1][k]]?dp[l][k]:dp[r-(1<<k)+1][k];
}
int main()
{
int m,pos,k,i;
while(scanf("%s %d",num,&m)==2)
{
pos=0;
k=0;
i=0;
GetRMQ(strlen(num));
while(m+i<strlen(num))
{
pos=Query(pos,m+i);
res[k++]=num[pos++];
i++;
}
for(i=0;i<k;i++)
if(res[i]!='0')
break;
if(i==k)
putchar('0');
else
{
for(;i<k;i++)
putchar(res[i]);
}
putchar('\n');
}
return 0;
}HDU ACM 3183 A Magic Lamp->RMQ的ST算法或贪心
原文地址:http://blog.csdn.net/a809146548/article/details/45479553