题解

非常容易想到的线段树, 还可以用并查集来。 还有一位大神用了$O(n)$ 就过了Orz

要判断是否能染色出输入给出的序列,必须满足两个条件:

1、 序列中必须存在一个$q$

2、 两个相同的数$x$的中间不存在比 $ x$ 小的数

首先判断输入的数列中是否存在$q$, 若不存在$q$ 且没有 $a_i = 0$, 表示序列中一定没有$q$, 直接输出NO

  若存在某个$a_i = 0$ , 将任意一个染成$q$即可

然后我们再查询两个相同的数$x$ 中是否存在比$x$ 小的数,用线段树来维护区间最小即可实现

  接着把两个$x$中间的序列染色, 用MinOK来记录,表示区间内$a_i = 0$,可以染色的最小值。 (线段树区间修改

  最后把$a_i = 0$ 进行染色(利用线段树点查询

CF现场就想到的算法,然而没有特判存在$q$,pushdown还少打了唔, CF百分百掉分,我要变成pupil了,太惨啦QAQ

代码

 #include<cstring>
#include<algorithm>
#include<cstdio>
#define lson nd<<1
#define rson nd<<1|1
#define rd read()
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define per(i,a,b) for(int i = (a); i >= (b); --i)
using namespace std; const int N = 3e5, inf = ~0U >> ; int MIN[N << ], a[N], L[N], R[N], lazy[N << ], q, n, pos;
int Mok[N << ]; int read() {
int X = , p = ; char c = getchar();
for(; c > '' || c < ''; c = getchar()) if( c == '-') p = -;
for(; c >= '' && c <= ''; c = getchar()) X = X * + c - '';
return X * p;
} void update(int nd) {
MIN[nd] = min(MIN[lson], MIN[rson]);
} void pushdown(int nd) {
if(lazy[nd]) {
Mok[lson] = lazy[nd];
Mok[rson] = lazy[nd];
lazy[lson] = lazy[rson] = lazy[nd];
lazy[nd] = ;
}
} void build(int l, int r, int nd) {
if(l == r) {
MIN[nd] = a[l] == ? inf : a[l];
return;
}
int mid = (l + r) >> ;
build(l, mid, lson);
build(mid + , r, rson);
update(nd);
} int query(int Li, int Ri, int l, int r, int nd) {//查询区间最小
if(Li <= l && r <= Ri) return MIN[nd];
int mid = (l + r) >> , re = inf;
if(Li <= mid) re = min(re, query(Li, Ri, l, mid, lson));
if(mid < Ri) re = min(re, query(Li, Ri, mid + , r, rson));
return re;
} int query_pt(int p, int l, int r, int nd) {//查询可以染上的值
if(l == r) return Mok[nd];
int mid = (l + r) >> ;
pushdown(nd);
if(p <= mid) return query_pt(p, l, mid, lson);
else return query_pt(p, mid + , r, rson);
} void change(int Li, int Ri, int c, int l, int r, int nd) {
if(Li <= l && r <= Ri) {
lazy[nd] = c;
Mok[nd] = c;
return;
}
int mid = (l + r) >> ;
pushdown(nd);
if(Li <= mid) change(Li, Ri, c, l, mid, lson);
if(mid < Ri) change(Li, Ri, c, mid + , r, rson);
update(nd);
} int main()
{
n = rd; q = rd;
for(int i = ; i <= n; ++i) {
a[i] = rd;
if(!a[i]) pos = i;
if(!L[a[i]]) L[a[i]] = i;
R[a[i]] = i;
}
if(!L[q] && !pos) return printf("NO\n"), ;//无a[i]=0也无q
build(, n, );
for(int i = ; i <= q; ++i) {//必须按颜色从小到大覆盖
if(!L[i]) continue;
int minv = query(L[i], R[i], , n, );
if(minv < i) return printf("NO\n"), ;
change(L[i], R[i], i, , n, );
}
for(int i = ; i <= n; ++i) if(!a[i]) {
a[i] = query_pt(i, , n, );
if(i == pos && !L[q]) a[i] = q; // 必须存在q
else if(!a[i]) a[i] = ;
}
printf("YES\n");
for(int i = ; i <= n; ++i) printf("%d ", a[i]);
putchar('\n');
}

CF 1023D Array Restoration - 线段树的更多相关文章

  1. Codeforces #504(div1+div2) 1023D Array Restoration(线段树)

    题目大意:给你一个数组,数组是经过q次区间覆盖后的结果,第i次覆盖是把区间内的值赋值为i,其中有若干个地方数值未知(就是0),让你判断这个数组是否可以经过覆盖后得到的,如果可以,输出任意一种可行数组. ...

  2. CF1114F Please, another Queries on Array?(线段树,数论,欧拉函数,状态压缩)

    这题我在考场上也是想出了正解的……但是没调出来. 题目链接:CF原网 题目大意:给一个长度为 $n$ 的序列 $a$,$q$ 个操作:区间乘 $x$,求区间乘积的欧拉函数模 $10^9+7$ 的值. ...

  3. Codedforces 1076G Array Game 线段树

    题意 现在cf上看题意真nm麻烦,有道网页翻译和谷歌翻译鬼畜的一匹 两个人在玩一个游戏. 有一个有\(n\)个数序列\(B\),一开始有一个棋子在\(B\)的第一个位置. 双方轮流操作,第一次操作前将 ...

  4. codeforces 482B. Interesting Array【线段树区间更新】

    题目:codeforces 482B. Interesting Array 题意:给你一个值n和m中操作,每种操作就是三个数 l ,r,val. 就是区间l---r上的与的值为val,最后问你原来的数 ...

  5. CF 787D Legacy(线段树思想构图+最短路)

    D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  6. Light OJ-1082 - Array Queries,线段树区间查询最大值,哈哈,水过~~

                                                                                                        ...

  7. Codeforces E. Interesting Array(线段树)

    题目描述: D. Interesting Arraytime limit per test1 secondmemory limit per test256 megabytesinputstandard ...

  8. B. Interesting Array(线段树)

    B. Interesting Array time limit per test 1 second memory limit per test 256 megabytes input standard ...

  9. CF 19D Points 【线段树+平衡树】

    在平面上进行三种操作: 1.add x y:在平面上添加一个点(x,y) 2.remove x y:将平面上的点(x,y)删除 3.find x y:在平面上寻找一个点,使这个点的横坐标大于x,纵坐标 ...

随机推荐

  1. Executor框架(三)线程池详细介绍与ThreadPoolExecutor

    本文将介绍线程池的设计细节,这些细节与 ThreadPoolExecutor类的参数一一对应,所以,将直接通过此类介绍线程池. ThreadPoolExecutor类 简介   java.uitl.c ...

  2. 一、探索 Android Studio

    探索 Android Studio 本文内容 项目结构 界面 Gradle 构建系统 调试和分析工具 Android Studio 是基于 IntelliJ IDEA 的官方 Android 应用开发 ...

  3. 从最大似然函数 到 EM算法详解

    极大似然算法 本来打算把别人讲的好的博文放在上面的,但是感觉那个适合看着玩,我看过之后感觉懂了,然后实际应用就不会了.... MLP其实就是用来求模型参数的,核心就是“模型已知,求取参数”,模型的意思 ...

  4. sklearn的estimator

    estimator的工作流程 在sklearn中,估计器(estimator)是一个重要的角色,分类器和回归器都属于estimator.在估计器中有有两个重要的方法是fit和transform. fi ...

  5. Sklearn数据集与机器学习

    sklearn数据集与机器学习组成 机器学习组成:模型.策略.优化 <统计机器学习>中指出:机器学习=模型+策略+算法.其实机器学习可以表示为:Learning= Representati ...

  6. python json.loads json.dumps(ensure_ascii = False) 汉字乱码问题解决

    python 转换为json时候 汉字编码问题 2017年03月23日 18:50:04 阅读数:5604 有这样一个需求: 需要一个json 文件 数据从数据库里查询出来 1. 设置文件头 # -* ...

  7. 3.mybatis实战教程(mybatis in action)之三:实现数据的增删改查

    转自:https://blog.csdn.net/tangruyi1992/article/details/52583910 前面已经讲到用接口的方式编程.这种方式,要注意的一个地方就是.在User. ...

  8. 反射(hasattr , getattr, setattr) 输入的字符串用来运行程序

    当用户输入字符串时,不能够用来运行程序 1.使用 hasattr 找出输入的字符串是否在程序内 2.使用 getattr 返回找出字符串对应的函数的内存地址或者变量 3. 使用setattr 添加新的 ...

  9. as3 中 final 修饰符

    现在,在ActionScript 3.0的修饰符中,只有final修饰符没有介绍.之所有放在这里介绍,是因为final修饰符只与继承有关,指定一个方法不能被重写或一个类不能被继承. 一般来说,当用fi ...

  10. mongodb基础学习9-分片

    分片和复制集不同,复制集是多个实例存储相同的内容,而分片是将内容存储到不同的分片上,不同分片存储的数据不同 下面看看具体的操作: 先启动两个片的实例: 再启动configsvr,要加上configsv ...