• 序列 [构造题]


    序列


    color{red}{正解部分}

    首先 最多有一个数字同时出现在 最长上升子序列最长下降子序列 中, 所以若 A+B>N+1A+B > N+1, 说明 无解 .

    然后考虑怎么构造, 将 {1,2,3...N}{1,2,3...N} 分成若干个大小为 BB 的块(可能会剩下一个小块), 总共有 a=NBa = lceil frac{N}{B} ceil 个块,

    最长上升子序列 的长度至少为 aa, 若 A<aA < a, 说明 无解 .
    否则可以在 内反转元素, 每反转一次 最长上升子序列 的长度会增加 11, 最长下降子序列 的长度不变 .

    按上述方法构造即可 .


    color{red}{实现部分}

    将剩余部分放在前面

    #include<bits/stdc++.h>
    #define reg register
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 1e5 + 10;
    
    int N;
    int A;
    int B;
    
    bool used[maxn];
    
    void Work(){
            N = read(), A = read(), B = read();
            for(reg int i = 1; i <= N; i ++) used[i] = 0;
            int left = N / B;
            if(N % B) left ++;
            if(A+B > N+1 || A < left){ printf("No
    "); return ; }
            printf("Yes
    ");
            int base = N % B;      
            for(reg int i = 1; i <= A-left; i ++){
                    used[i] = 1, printf("%d ", i);
                    if((i - base) % B == 0) A ++;
            }
            int t = N%B;
            while(t <= N){
                    int t2 = std::max(1, t - B + 1), tmp = t;
                    while(tmp >= t2){
                            if(!used[tmp]) printf("%d ", tmp);
                            tmp --;
                    }
                    t += B;
            }
            printf("
    ");
            /*
            if(t >= N + 1){
                    for(reg int j = 0 ; j < t; j ++) printf("%d ", ++ cur);
            }
            for(reg int i = 1; i <= B; i ++) printf("%d ", i-1);
            */
    }
    
    int main(){
            int T = read();
            while(T --) Work();
            return 0;
    }
    

    将剩余部分放在后面

    #include<bits/stdc++.h>
    #define reg register
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 1e6 + 10;
    
    int N;
    int A;
    int B;
    
    bool used[maxn];
    
    void Work(){
            N = read(), A = read(), B = read();
            for(reg int i = 1; i <= N; i ++) used[i] = 0;
            int left = N / B;
            if(N % B) left ++;
            if(A+B > N+1 || A < left){ printf("No
    "); return ; }
            printf("Yes
    ");
            for(reg int i = 1; i <= A-left; i ++){
                    used[i] = 1, printf("%d ", i);
                    if(i % B == 0) A ++;
            }
            int t = B;
            while(t <= N){
                    int t2 = t - B + 1, tmp = t;
                    while(tmp >= t2){
                            if(!used[tmp]) printf("%d ", tmp);
                            tmp --;
                    }
                    t += B;
            } 
            for(reg int i = N; i >= N-(N%B)+1; i --) if(!used[i]) printf("%d ", i);
            printf("
    ");
    }
    
    int main(){
            freopen("seq.in", "r", stdin);
            freopen("seq.out", "w", stdout);
            int T = read();
            while(T --) Work();
            return 0;
    }
    
  • 相关阅读:
    Go语言new( )函数
    Go语言讲解深拷贝与浅拷贝
    (转)使用kubectl访问Kubernetes集群时的身份验证和授权
    执行kubectl命令时报错 error: You must be logged in to the server (Unauthorized)
    报错 cannot allocate memory 或者 no space left on device ,修复K8S内存泄露问题
    linux之apt-get命令(转)
    GSensor 碰撞检测方法与实现
    uboot流程(转)
    linux 环境搭建
    333开发记录
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822452.html
Copyright © 2020-2023  润新知