CF 1023D Array Restoration - 线段树
题解
非常容易想到的线段树, 还可以用并查集来。 还有一位大神用了$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 - 线段树的更多相关文章
- Codeforces #504(div1+div2) 1023D Array Restoration(线段树)
题目大意:给你一个数组,数组是经过q次区间覆盖后的结果,第i次覆盖是把区间内的值赋值为i,其中有若干个地方数值未知(就是0),让你判断这个数组是否可以经过覆盖后得到的,如果可以,输出任意一种可行数组. ...
- CF1114F Please, another Queries on Array?(线段树,数论,欧拉函数,状态压缩)
这题我在考场上也是想出了正解的……但是没调出来. 题目链接:CF原网 题目大意:给一个长度为 $n$ 的序列 $a$,$q$ 个操作:区间乘 $x$,求区间乘积的欧拉函数模 $10^9+7$ 的值. ...
- Codedforces 1076G Array Game 线段树
题意 现在cf上看题意真nm麻烦,有道网页翻译和谷歌翻译鬼畜的一匹 两个人在玩一个游戏. 有一个有\(n\)个数序列\(B\),一开始有一个棋子在\(B\)的第一个位置. 双方轮流操作,第一次操作前将 ...
- codeforces 482B. Interesting Array【线段树区间更新】
题目:codeforces 482B. Interesting Array 题意:给你一个值n和m中操作,每种操作就是三个数 l ,r,val. 就是区间l---r上的与的值为val,最后问你原来的数 ...
- CF 787D Legacy(线段树思想构图+最短路)
D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...
- Light OJ-1082 - Array Queries,线段树区间查询最大值,哈哈,水过~~
...
- Codeforces E. Interesting Array(线段树)
题目描述: D. Interesting Arraytime limit per test1 secondmemory limit per test256 megabytesinputstandard ...
- B. Interesting Array(线段树)
B. Interesting Array time limit per test 1 second memory limit per test 256 megabytes input standard ...
- CF 19D Points 【线段树+平衡树】
在平面上进行三种操作: 1.add x y:在平面上添加一个点(x,y) 2.remove x y:将平面上的点(x,y)删除 3.find x y:在平面上寻找一个点,使这个点的横坐标大于x,纵坐标 ...
随机推荐
- python+selenium:iframe框架中多种定位
方法一:通过索引,id,name,WebElement定位 from selenium import webdriverdriver = webdriver.Firefox()driver.switc ...
- UVA548
题意: 根据二叉树中序和后序建立二叉树,从根结点开始计算和到叶子结点,输出总和最小的叶子结点,如果有俩个和一样大,输出叶子结点最小的 AC:80ms #include<stdio.h> # ...
- mysql常见问题解决方法.
1. 问题:mysql启动报错(linux) [root@localhost ~]# service mysqld restart Another MySQL daemon already runni ...
- Node fs, url, http 组合小型的服务器 ( 满足html请求, get, post 传值 )
<script type="text/javascript"> /* * 引入模块 */ var http = require('http'); var url = r ...
- 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 ...
- 13 python 常用的内置方法介绍
1.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object) ...
- 压缩文件tar.gz和zip之间的区别
我们在开发的时候通常要先下载相关的软件或者是源码,或者是jar包.在下载东西的时候总是碰见后缀是.tar.gz和.zip的问题,搞不清楚是怎么回事,不晓得下载哪个文件才是对自己有用的.现在我知道了,其 ...
- Python之类属性的增删改查
#类属性又称为静态变量,或者是静态数据,这些数据是他们所属的类对象绑定的,不依赖于任何类实例 class ChinesePeople: country = 'china' def __init__(s ...
- ubuntu下安装jdk,tomcat,mysql,ftp,telnet,svn
需求分析:自己弄了个小网站,想放到云服务器上,同时把自己积累的代码也放上去,服务器上的文件可以简单的在windows上查看,也可以方便的通过windows连接linux服务器. 解决:运行网站要用到j ...
- htop工具使用
1 防止进程重复显示 在使用htop查看进程信息的时候,经常会出现很多个进程重复的情况,如下情况: 经研究发现,htop会把一个进程里的线程当做一个进程来显示出来,上图中的java进程有多个线程,所以 ...