zoukankan      html  css  js  c++  java
  • 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("
    ");
    }
    
  • 相关阅读:
    linux入门学习
    qt 常见问题记录
    我今年,二十七八岁了
    C#程序如何实现设置系统WIFI共享
    主界面设计(收集)
    Qt中如何添加ICON图标
    系统登录界面(收集)
    Qt类型转换
    qt 系统设计对比
    Qt中丰富的容器类数组QVector、链表QLinkedList、映射表QMap、哈希表QHash
  • 原文地址:https://www.cnblogs.com/ucprer/p/11801432.html
Copyright © 2011-2022 走看看