• Songwriter CF1252-E(贪心)


    题意:

    已知一个序列a,问能否将a映射到序列b,使得相邻元素之间的大小关系不变(三种),且相邻元素不能相差超过k,且每个元素范围在[L,R]内。如果能,求字典序最小的b。

    思路:

    可以设b[1]的范围为[L,R],从前往后遍历求出b[2]~b[n]每个元素的上界和下界。如果其中有元素已经没有可以使之前成立的范围了,那么说明无法构造这样的映射。

    此时最后一个元素的上下界是正确的,从后往前遍历即可得到正确序列B,但是若要保证字典序最小,则每个元素应该取最小的可行取值(如果开始先从后往前扫求出范围,再从前往后贪心地选最小取值更容易理解,但是反过来也是正确的贪心策略)。

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+5;
    int l[maxn],r[maxn],a[maxn];
    int ans[maxn];
    int main(){
        int n,L,R,k;
        cin>>n>>L>>R>>k;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        l[1]=L;r[1]=R;
        for(int i=2;i<=n;i++){
            if(a[i]==a[i-1]){
                l[i]=l[i-1];
                r[i]=r[i-1];
            }
            else if(a[i]>a[i-1]){
                l[i]=l[i-1]+1;
                r[i]=min(r[i-1]+k,R);
            }
            else if(a[i]<a[i-1]){
                l[i]=max(L,l[i-1]-k);
                r[i]=r[i-1]-1;
            }
            if(l[i]>r[i]||r[i]<L||l[i]>R){
                printf("-1
    ");
                return 0;
            }
        }
        ans[n]=l[n];
        for(int i=n-1;i>=1;i--){
            if(a[i]==a[i+1])
                ans[i]=ans[i+1];
            else if(a[i]<a[i+1]){
                //ans[i+1]-k<=ans[i]<=ans[i+1]-1
                //l[i]<=ans[i]<=r[i]
                ans[i]=max(ans[i+1]-k,l[i]);
            }
            else if(a[i]>a[i+1]){
                //ans[i+1]+1<=ans[i]<=ans[i+1]+k
                //l[i]<=ans[i]<=r[i]
                ans[i]=max(ans[i+1]+1,l[i]);
            }
        }
        for(int i=1;i<=n;i++){
            printf("%d ",ans[i]);
        }
        printf("
    ");
    }
    
  • 相关阅读:
    影响指令流水线的因素
    硬布线控制器和微程序控制器 
    总线仲裁
    计算机专业面试
    P、NP、NPC、NPH问题的区别和联系
    多态
    软件生命周期
    你所不知道的js的小知识点(1)
    html span标签 不换行(有时span带中文时候是可以自动换行的)
    form的onsubmit事件--表单提交前的验证最佳实现方式
  • 原文地址:https://www.cnblogs.com/ucprer/p/11801432.html
Copyright © 2020-2023  润新知