码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3183 A Magic Lamp

时间:2016-04-30 23:41:32      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:

  第一种做法是贪心做法,只要前面的数比后面的大就把他删掉,这种做法是正确的,也比较好理解,这里就不说了,我比较想说一下ST算法,RMQ的应用

主要是返回数组的下标,RMQ要改成<=(这里是个坑点,取连续数是可以的),他的转移方程为x = dp[i-1][j],y = dp[i-1][j+1<<(i-1)];

dp[i][j] = a[x] <= a[y] ? x : y;  这里既是转化为取n-m个数,首先在1 ~ m+1中必然选一个数,所以这个数就是n-m数中第一个数,记录所选的位置id,下次便是id+1,m++;

m++ = id + m + 1 - (id - 1),反证法可以很好的证明上述结论,稍微有点难想,如此看来,dp[i][j]将返回i 到 i+2<<j-1的最小值的下标;

说到这里我们应该感受到了,重要的是理解选数的过程,RMQ只是个优化...这个思维过程还是希望读者好好体会一下的.

#include<cstdio>
#include<cstring>
#include<cmath>

char s[1010];
char ans[1020];
int st[1010][20];

int Min(int x,int y)
{
    return s[x] <= s[y] ? x : y;
}

void RMQ_Init(int len)
{
    for(int i = 0; i < len; i++)
    st[i][0] = i;
    for(int j = 1; (1<<j) < len; j++)
    for(int i = 0; i+(1<<j)-1 < len;i++)
    st[i][j] = Min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}

int Query(int l,int r)
{
    int k = (int)(log((double)(r-l+1))/log(2.0));
    return Min(st[l][k],st[r-(1<<k)+1][k]);
}

int main()
{
    int len, m, i;
    while(scanf("%s%d",s, &m)!=EOF)
    {
        len = strlen(s);
        RMQ_Init(len);
        m = len - m;
        int pos = 0, num = 0;
        while(m--)
        {
            pos = Query(pos, len - m - 1);
            ans[num++] = s[pos++];
        }
        for(i = 0; i < num; i++)
            if(ans[i]!=0)
                break;
        if(i == num)
            printf("0");
        else
        {
            while(i < num)
                printf("%c",ans[i++]);
        }
        puts("");
    }
    return 0;
}

 

HDU 3183 A Magic Lamp

标签:

原文地址:http://www.cnblogs.com/jifahu/p/5449556.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!