题解

非常容易想到的线段树, 还可以用并查集来。 还有一位大神用了$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

代码

  1. #include<cstring>
  2. #include<algorithm>
  3. #include<cstdio>
  4. #define lson nd<<1
  5. #define rson nd<<1|1
  6. #define rd read()
  7. #define rep(i,a,b) for(int i = (a); i <= (b); ++i)
  8. #define per(i,a,b) for(int i = (a); i >= (b); --i)
  9. using namespace std;
  10.  
  11. const int N = 3e5, inf = ~0U >> ;
  12.  
  13. int MIN[N << ], a[N], L[N], R[N], lazy[N << ], q, n, pos;
  14. int Mok[N << ];
  15.  
  16. int read() {
  17. int X = , p = ; char c = getchar();
  18. for(; c > '' || c < ''; c = getchar()) if( c == '-') p = -;
  19. for(; c >= '' && c <= ''; c = getchar()) X = X * + c - '';
  20. return X * p;
  21. }
  22.  
  23. void update(int nd) {
  24. MIN[nd] = min(MIN[lson], MIN[rson]);
  25. }
  26.  
  27. void pushdown(int nd) {
  28. if(lazy[nd]) {
  29. Mok[lson] = lazy[nd];
  30. Mok[rson] = lazy[nd];
  31. lazy[lson] = lazy[rson] = lazy[nd];
  32. lazy[nd] = ;
  33. }
  34. }
  35.  
  36. void build(int l, int r, int nd) {
  37. if(l == r) {
  38. MIN[nd] = a[l] == ? inf : a[l];
  39. return;
  40. }
  41. int mid = (l + r) >> ;
  42. build(l, mid, lson);
  43. build(mid + , r, rson);
  44. update(nd);
  45. }
  46.  
  47. int query(int Li, int Ri, int l, int r, int nd) {//查询区间最小
  48. if(Li <= l && r <= Ri) return MIN[nd];
  49. int mid = (l + r) >> , re = inf;
  50. if(Li <= mid) re = min(re, query(Li, Ri, l, mid, lson));
  51. if(mid < Ri) re = min(re, query(Li, Ri, mid + , r, rson));
  52. return re;
  53. }
  54.  
  55. int query_pt(int p, int l, int r, int nd) {//查询可以染上的值
  56. if(l == r) return Mok[nd];
  57. int mid = (l + r) >> ;
  58. pushdown(nd);
  59. if(p <= mid) return query_pt(p, l, mid, lson);
  60. else return query_pt(p, mid + , r, rson);
  61. }
  62.  
  63. void change(int Li, int Ri, int c, int l, int r, int nd) {
  64. if(Li <= l && r <= Ri) {
  65. lazy[nd] = c;
  66. Mok[nd] = c;
  67. return;
  68. }
  69. int mid = (l + r) >> ;
  70. pushdown(nd);
  71. if(Li <= mid) change(Li, Ri, c, l, mid, lson);
  72. if(mid < Ri) change(Li, Ri, c, mid + , r, rson);
  73. update(nd);
  74. }
  75.  
  76. int main()
  77. {
  78. n = rd; q = rd;
  79. for(int i = ; i <= n; ++i) {
  80. a[i] = rd;
  81. if(!a[i]) pos = i;
  82. if(!L[a[i]]) L[a[i]] = i;
  83. R[a[i]] = i;
  84. }
  85. if(!L[q] && !pos) return printf("NO\n"), ;//无a[i]=0也无q
  86. build(, n, );
  87. for(int i = ; i <= q; ++i) {//必须按颜色从小到大覆盖
  88. if(!L[i]) continue;
  89. int minv = query(L[i], R[i], , n, );
  90. if(minv < i) return printf("NO\n"), ;
  91. change(L[i], R[i], i, , n, );
  92. }
  93. for(int i = ; i <= n; ++i) if(!a[i]) {
  94. a[i] = query_pt(i, , n, );
  95. if(i == pos && !L[q]) a[i] = q; // 必须存在q
  96. else if(!a[i]) a[i] = ;
  97. }
  98. printf("YES\n");
  99. for(int i = ; i <= n; ++i) printf("%d ", a[i]);
  100. putchar('\n');
  101. }

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. python+selenium:iframe框架中多种定位

    方法一:通过索引,id,name,WebElement定位 from selenium import webdriverdriver = webdriver.Firefox()driver.switc ...

  2. UVA548

    题意: 根据二叉树中序和后序建立二叉树,从根结点开始计算和到叶子结点,输出总和最小的叶子结点,如果有俩个和一样大,输出叶子结点最小的 AC:80ms #include<stdio.h> # ...

  3. mysql常见问题解决方法.

    1. 问题:mysql启动报错(linux) [root@localhost ~]# service mysqld restart Another MySQL daemon already runni ...

  4. Node fs, url, http 组合小型的服务器 ( 满足html请求, get, post 传值 )

    <script type="text/javascript"> /* * 引入模块 */ var http = require('http'); var url = r ...

  5. Error 2503 and 2502 when installing/uninstalling on Windows 10

    1. Hold Ctrl+Shift and press Esc. 2. Locate “Windows Explorer” under “Windows processes”, now right ...

  6. 13 python 常用的内置方法介绍

    1.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object) ...

  7. 压缩文件tar.gz和zip之间的区别

    我们在开发的时候通常要先下载相关的软件或者是源码,或者是jar包.在下载东西的时候总是碰见后缀是.tar.gz和.zip的问题,搞不清楚是怎么回事,不晓得下载哪个文件才是对自己有用的.现在我知道了,其 ...

  8. Python之类属性的增删改查

    #类属性又称为静态变量,或者是静态数据,这些数据是他们所属的类对象绑定的,不依赖于任何类实例 class ChinesePeople: country = 'china' def __init__(s ...

  9. ubuntu下安装jdk,tomcat,mysql,ftp,telnet,svn

    需求分析:自己弄了个小网站,想放到云服务器上,同时把自己积累的代码也放上去,服务器上的文件可以简单的在windows上查看,也可以方便的通过windows连接linux服务器. 解决:运行网站要用到j ...

  10. htop工具使用

    1 防止进程重复显示 在使用htop查看进程信息的时候,经常会出现很多个进程重复的情况,如下情况: 经研究发现,htop会把一个进程里的线程当做一个进程来显示出来,上图中的java进程有多个线程,所以 ...