HDU 3183 RMQ(指定区间的最值)

A Magic Lamp

题意很简单,自己好好读一下。

因为留下来的数要构成最小的数,所以我们可以先找字段里面最小的数字,
比如样例 a=178534 4 ;也就是说我们需要按顺序找到3个最小数,比如找第一个小的数,只能在a[0]...a[3]中找,第二个小的数,只能在a[1]...a[4]中找,诸如这样的找法一直找到所有需要找的数。
刚开始我是这样写的;

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int x;
    int d;
};
node a[1010];
int m;
char ch[1010];
int main()
{
    while(scanf("%s ",ch)!=EOF)
    {
        scanf("%d",&m);
        int len=strlen(ch);
        for(int i=0; i<len; i++)
        {
            a[i].x=ch[i]-'0';
            a[i].d=0;
        }
        int dd=len-m;
        int b[1010];
        for(int i=0; i<dd; i++)
        {
            int mm=99999,flag;
            for(int j=i; j<i+m+1; j++)
            {
                if(a[j].x<mm && !a[j].d)
                {
                    mm=a[j].x;
                    flag=j;
                }
            }
            a[flag].d=1;
            b[i]=mm;
        }
        int ans=0;
        for(int i=0; i<dd; i++)
        {
            ans=ans*10+b[i];
        }
        cout<<ans<<endl;

    }
    return 0;
}

但是这样的弊端就是,有可能找到的数字的顺序是不对的,刚开始没意识到,也是今天晚上打cf之前想到的;

这是ST(就是个动态规划的思想)的解法,只有理解了RMQ的f[i][j]跳转的方式和意义,就能很好的应用了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define inf 0x3f3f3f3f3f
char a[1010],num[1010];
int len,n;
int f[1010][15];
int Min(int i,int j)
{
    return a[i]<=a[j]?i:j;
}
void RMQ(int n)
{
    for(int i=0; i<n; i++)
        f[i][0]=i;
    for(int j=1; j<=(int)(log(1.0*n)/log(2.0)); j++)
    {
        for(int i=0; i+(1<<j)-1<n; i++)
        {
            f[i][j]=Min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
        }
    }
}
int qq(int l,int r)
{
    int x=(int)(log(1.0*(r-l+1))/log(2.0));
    return Min(f[l][x],f[r-(1<<x)+1][x]);
}
int main()
{
    while(scanf("%s ",a)!=EOF)
    {
        scanf("%d",&n);
        len=strlen(a);
        RMQ(len);
        n=len-n;
        int i=0,j=0;
        while(n--)
        {
            i=qq(i,len-n-1);
            num[j++]=a[i++];
        }
        for(i=0; i<j; i++)
            if(num[i]!='0')
            break;
        if(i==j)
        {
            printf("0\n");
            continue;
        }
        else
        {
            for( ;i<j; i++)
                printf("%c",num[i]);
        }
        printf("\n");
    }
    return 0;
}

你可能感兴趣的:(HDU 3183 RMQ(指定区间的最值))