Codeforce101061E-Playing with numbers(RMQ-ST)

  • Playing with numbers
  • 题意:
  • 给你两个数字s和n,在不改变s的数字顺序下,删除n个数使剩下来的数最大或最小。(包含前导零)。并且n不会大于s的长度。
  • 思路:
  • 给出数字s就一定知道数字s的长度lenlen个数字删除n个数字,那么剩下X=len-n个数字。要使得这X个数字组成的数W最小。所以最高位首先应该最小。那首位的范围在哪呢?假如在全部的数字(1~len)中查找,那假如最后一个数字最小,组合的数字W的第二位肯定在第一位后面,那就不可行了,就找不到X个数字了。所以极端的思想就是找到len个数字最后的X个数字组合的数就是我们要求的最大数或最小数。那么第一个数字一定在(1~n+1)中出现。
  • 我们可以这样来模拟一下:假设A数组就只有6个数,分别是A[1],A[2],A[3],A[4],A[5],A[6],我们去掉 n=2个数,使形成的值最小。
    那么我们此时的len=6,n=2X=len-n=4
    则我们说形成的4位数的第一位一定在区间[1,3]中出现,因为如果区间范围再大点,比如[1,4],这样就不科学了,因为第一位一定不会是A[4],更不会是
    A[5],A[6],我们假设可以是A[4],那么后面只有A[5],A[6]两位数了,这样的话最多只可能形成3位数,绝对不能形成len-n=4位了。
    当然到了这里,我们就可以这样做了,第一位可以在区间[1,n+1]里面找,假设第一位在位置tem因为第二位肯定在第一位的后面,所以第二位一定存在于
    区间[tem+1,n+2],为什么是n+2,因为第一位已经确定了,现在只需要确定len-n-1位了,第二次继续采用极端的思想,len最后的几位符合情况,那么说明第二次的第一个数是n+2,搜索区间是[tem+1,n+2],所以区间就可以向后增加1,一直这样循环下去,就可以找到留下来的最大值或最小值。
#include
using namespace std;
queuequ1,qu2;
char s[100010];
int dpmaix[100010][24];//存放的是第i个字符开始,连续的2^j个字符的最大字符的下标
int dpminx[100010][24];//存放的是第i个字符开始,连续的2^j个字符的最小字符的下标
int n;
int findmaix(int x,int y)//返回较大字符的下标
{
    if(s[x]>=s[y])
    {
        return x;
    }
    else
    {
        return y;
    }
    
}
int findminx(int x,int y)//返回较小字符的下标
{
    if(s[x]<=s[y])
    {
        return x;
    }
    return y;
}
void ST(int n)
{
    for(int i=0;i>t;
    getchar( );
    while(t--)
    {
        while(!qu1.empty( ))
        {
            qu1.pop( );
        }
        while(!qu2.empty( ))
        {
            qu2.pop( );
        }
        scanf("%s %d",s,&n);
        //cout<

你可能感兴趣的:(Codeforce101061E-Playing with numbers(RMQ-ST))