Gym - 101806W - Winter Olympic Games

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/monochrome00/article/details/84533537

题目链接<https://cn.vjudge.net/problem/1595745/origin>


题意:

给出一段01串,要求把其中一段的子串替换成一个1,使得新得到的串字典序最大。输出要替换的子串。


题解:

贪心的想,最开始的几个连续的1不要碰,后面找一个字典序最大的后缀也保留,把中间的串替换掉。这样直接套一个后缀数组就能过了。

比赛的时候我没用后缀数组,自己想了一个算法也过了。还没被证伪,先写下来记下。

i记录当前字典序最大的后缀下标,j记录可能是更大字典序的下标。另外开一个pi,pj表示i和j往后延展比较。

  • 如果s[pi]>s[pj],也就是说i代表的后缀仍旧比j大,那么i不变,j跳到pj的位置上。
  • 如果s[pi]<s[pj],也就是说i代表的后缀比j小,那么i跳到j的位置上。j跳到pj前面第一次出现1的位置。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+7;
const int inf=1e9;
char s[N];
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",s+1);
    int ss;
    for(ss=1;ss<=n;ss++){
        if(s[ss]=='0') break;
    }
    if(ss>n){printf("0 0\n");return 0;}
    printf("%d ",ss-1);
    int i=ss,j=ss;
    while(i<=n&&j<=n){
        if((s[j]<s[i])||(i==j)){j++;continue;}
        if(s[j]>s[i]){i=j;continue;}
        int pi=i+1,pj=j+1;
        while(pi<=n&&pj<=n){
            if(s[pi]==s[pj]){pi++;pj++;continue;}
            if(s[pi]>s[pj]) break;
            i=j;
            while(s[pj-1]=='1') pj--;
            break;
        }
        j=pj;
    }
    printf("%d\n",i-ss);
}

猜你喜欢

转载自blog.csdn.net/monochrome00/article/details/84533537