zoukankan      html  css  js  c++  java
  • C. Vasya And Array (贪心构造)

    题目链接
    题意:给定长度为 n 的数组a, 有 m 个限制条件,要求构造出这个数组
    限制条件: ti li ri
    条件一 :ti == 1 , 在数组区间为 [li, ri] 是非递减的
    条件二 :ti == 0, 在数组区间为 [li, ri] 不是非递减的

    这样的C题对于我来说,体验还是很棒的,可是我没打

    思路:首先,对于非递减, 序列 5 5 5 5 5, 是符合的
    所以, 在这个题目里,我先把 ti == 1 的限制条件处理掉
    对于一些相交的是可以合并为一个区间的(想一下就知道了)
    这样,可能会得到一些区间是要满足限制一的,在限制二下, 按照贪心, 我们可以把这些区间从大到小构造
    最后, 限制二是否会起冲突

    #include <bits/stdc++.h>
    const int maxn = 1500;
    using namespace std;
    typedef long long ll;
    
    struct note{
        int l, r;
    } a[maxn];
    int vis[maxn], ans[maxn], n, m;
    //vis 标记数组
    
    int main()
    {
        int cnt = 0, col = 0;
        scanf("%d%d", &n, &m);
        while(m--){
            int op;
            scanf("%d%d%d", &op, &a[cnt].l, &a[cnt].r);
            if(op == 1){    //处理区间   标记 有可能会有合并
                int t = ++col;
                int qian = vis[a[cnt].l], hou = vis[a[cnt].r];
                t = (qian == 0) ? t : qian; //如果和前面的区间有交集,用前面区间的标记去覆盖
                for (int i = a[cnt].l; i<=a[cnt].r; i++)    //标记
                    vis[i] = t;
                for (int i = a[cnt].r + 1; i<=n; i++){  //覆盖后面的区间
                    if(hou && hou == vis[i])
                        vis[i] = t;
                    else
                        break;
                }
            }
            else
                cnt++;  //先保存,等下处理
        }
        ans[0] = 1500;  //取个较大的数
        for (int i = 1; i<=n; i++){
            if(vis[i] != vis[i-1]){
                ans[i] = ans[i - 1] - 1;
            }
            else{
                if(vis[i] == 0)
                    ans[i] = ans[i - 1] - 1;
                else        //限制一,在一个非递减子序列里
                    ans[i] = ans[i - 1];
            }
        }
        for (int i = 0; i < cnt; i++){
            /*
            没冲突情况
            1 区间里,有两个不同的非递减子序列
            2 区间里,至少有一个没被标记的点
             */
            int t = vis[a[i].l], mark = 0;
            for (int j = a[i].l + 1; j <= a[i].r; j++){
                if(vis[j] != t){
                    mark = 1;
                    break;
                }
            }
            if(!mark && t){ //冲突
                printf("NO
    ");
                return 0;
            }
        }
        printf("YES
    ");
        for (int i = 1; i<=n; i++){
            printf("%d ", ans[i]);
        }
        printf("
    ");
        return 0;
    }
    
  • 相关阅读:
    取目标描述
    DCLF RCVF SNDF SNDRCVF等用法
    CL过程监控JOB的错误消息
    取用户配置文件属性
    SNDBRKMSG 例子
    信息操作
    文件下载解决中文乱码
    table行的上移下移 上下移动
    常用表操作Sql语句
    sql删除重复行
  • 原文地址:https://www.cnblogs.com/jizhihong/p/13337352.html
Copyright © 2011-2022 走看看