D. Array Restoration

题目链接:https://codeforces.com/contest/1023/problem/D

题意:

给出一个序列,现在要求对一个全为0的序列执行q次操作,每次操作都要选定一段区间然后将区间上面的值变为i(i为操作的次数)。最终使得0序列变为之前给出的序列。

原序列中如果存在0,那么说明这个值是任意的。

最后要求输出经过q次操作之后的序列。

题解:

我们首先可以想到不可行的情况:在原序列中若存在一个数a,假设其出现次数大于1,那么两端为a的中间区间部分,是没有值比a小的。

还有一种情况也不可行,就是原序列中没有0且最大值小于q。

当把这两种情况排除过后,就是可行的情况了,之后输出方案就好了。

输出方案的时候还要解决0的问题,我的解决方案是让0等于其右边或左边的数,我是将一段连续的0缩点后进行处理的。

代码如下:

  1. #include <bits/stdc++.h>
  2. #define pii pair<int,int>
  3. #define INF 99999999
  4. using namespace std;
  5.  
  6. const int N = 2e5+;
  7. int n,q;
  8. int a[N],cnt[N];
  9. struct node{
  10. int l,r;
  11. }z[N],All[N];
  12. int f[N][];
  13. vector <int> vec[N];
  14. int main(){
  15. cin>>n>>q;
  16. int num = ,mx=;
  17. a[]=-;a[n+]=-;
  18. for(int i=;i<=n;i++){
  19. scanf("%d",&a[i]);
  20. mx=max(mx,a[i]);
  21. if(a[i]==&&a[i-]!=){
  22. num++;
  23. }
  24. if(a[i]==){
  25. cnt[i]=num;
  26. if(a[i-]!=) z[num].l=i-;
  27. }else if(a[i-]==) z[num].r=i;
  28. vec[a[i]].push_back(i);
  29. }
  30. if(a[n]==) z[num].r=n+;
  31. int flag = ;
  32. for(int i=;i<=n;i++){
  33. if(a[i]== || vec[a[i]].size()<=) continue ;
  34. int len = vec[a[i]].size()-;
  35. All[a[i]].l=vec[a[i]][];
  36. All[a[i]].r=vec[a[i]][len];
  37. }
  38. for(int i=;i<=n;i++) for(int j=;j<=;j++) f[i][j]=INF;
  39. for(int i=;i<=n;i++) f[i][]=(a[i]== ? INF : a[i]);
  40. for(int i=;i<=n;i++)
  41. for(int j=;j<=;j++)
  42. f[i][j]=min(f[i][j-],f[i+(1ll<<(j-))][j-]);
  43. for(int i=;i<=n;i++){
  44. if(vec[a[i]].size()<=) continue ;
  45. int l = All[a[i]].l,r = All[a[i]].r;
  46. l++;r--;
  47. int K = log((r-l+));
  48. int mn = min(f[l][K],f[r-(<<K)+][K]);
  49. if(mn<a[i]){
  50. flag=;
  51. break ;
  52. }
  53. }
  54. int ok=;
  55. if(q>mx) ok=;
  56. if(ok) for(int i=;i<=n;i++){
  57. if(a[i]==){
  58. a[i]=q;
  59. ok=;
  60. break ;
  61. }
  62. }
  63. if(flag||ok==) cout<<"NO";
  64. else{
  65. cout<<"YES"<<endl;
  66. for(int i=;i<=n;i++){
  67. if(a[i]!=){
  68. cout<<a[i]<<" ";
  69. }
  70. else{
  71. int l = z[cnt[i]].l,r = z[cnt[i]].r;
  72. if(l< && r>n) cout<<q<<" ";
  73. else if(l<) cout<<a[r]<<" ";
  74. else cout<<a[l]<<" ";
  75. }
  76. }
  77. }
  78. return ;
  79. }

之后看了下标程,用的是并查集orz...

标程的想法就比较巧妙了,首先把之前说的第二种不可行情况判断一下,然后开始骚操作。

其基本思想为:值从大到小进行区间修改的操作,对于当前位置的数而言,用并查集来维护i之后小于或等于它的第一个位置

因为我们是从大到小开始涂色,对于第一次涂色,肯定能找到第一个小于或等于它的位置;对于第i次涂色,假设当前位置为pos,如果pos+1的值比pos的值大,那么它之前已经操作过了,说明已经用并查集处理过了,那么f(pos+1)就是比pos+1的值小的第一个位置;如果此时找到的值还比pos的值大,那么就继续寻找;如果比pos的值小,那么就不可行。

注意上面查找值时要满足值的存在区间范围,并且为了输出方案,我们还要对区间进行修改,这时只用对0进行修改就好了~比它大的都不用管。

具体代码如下:

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int N =2e5+;
  5. int n,q;
  6. int f[N],l[N],r[N];
  7. int a[N];
  8.  
  9. int find(int x){
  10. return f[x]==x ? f[x] : f[x]=find(f[x]);
  11. }
  12.  
  13. int main(){
  14. cin>>n>>q;
  15. for(int i=;i<=q;i++) l[i]=n+,r[i]=;
  16. for(int i=;i<=n+;i++) f[i]=i;
  17. for(int i=;i<=n;i++){
  18. scanf("%d",&a[i]);
  19. l[a[i]]=min(l[a[i]],i);
  20. r[a[i]]=max(r[a[i]],i);
  21. }
  22. if(l[q]>r[q]){
  23. if(l[]>r[]){
  24. cout<<"NO";
  25. return ;
  26. }
  27. a[l[]]=q;
  28. f[l[]]=l[]+;
  29. }
  30. for(int i=q;i>=;i--){
  31. for(int j=find(l[i]);j<=r[i];j=find(j)){
  32. if(a[j] && a[j]<i){
  33. cout<<"NO";
  34. return ;
  35. }
  36. a[j]=i;
  37. f[j]=find(j+);
  38. }
  39. }
  40. puts("YES");
  41. for(int i=;i<=n;i++) printf("%d ",a[i]?a[i]:);
  42. return ;
  43. }

Codeforces Round #504:D. Array Restoration的更多相关文章

  1. Codeforces Round #504 D. Array Restoration

    Codeforces Round #504 D. Array Restoration 题目描述:有一个长度为\(n\)的序列\(a\),有\(q\)次操作,第\(i\)次选择一个区间,将区间里的数全部 ...

  2. Codeforces Round #504 E. Down or Right

    Codeforces Round #504 E. Down or Right 题目描述:交互题. 有一个\(n \times n\)的方阵,有一些格子是障碍,从\((1, 1)\)出发,只能向右向下走 ...

  3. Codeforces 1023 A.Single Wildcard Pattern Matching-匹配字符 (Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Fi)

    Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final) A. Single Wildcard Patter ...

  4. Codeforces 1023 D.Array Restoration-RMQ(ST)区间查询最值 (Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Fi)

    D. Array Restoration 这题想一下就会发现是只要两个相同的数之间没有比它小的就可以,就是保存一下数第一次出现和最后一次出现的位置,然后查询一下这个区间就可以,如果有0的话就进行填充. ...

  5. [Educational Codeforces Round 63 ] D. Beautiful Array (思维+DP)

    Educational Codeforces Round 63 (Rated for Div. 2) D. Beautiful Array time limit per test 2 seconds ...

  6. Codeforces Round #504 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)-D- Array Restoration

    我们知道不满足的肯定是两边大中间小的,这样就用RMQ查询两个相同等值的区间内部最小值即可,注意边界条件 #include<bits/stdc++.h> #define x first #d ...

  7. Educational Codeforces Round 11 A. Co-prime Array 水题

    A. Co-prime Array 题目连接: http://www.codeforces.com/contest/660/problem/A Description You are given an ...

  8. Educational Codeforces Round 23 D. Imbalanced Array 单调栈

    D. Imbalanced Array time limit per test 2 seconds memory limit per test 256 megabytes input standard ...

  9. Educational Codeforces Round 11——A. Co-prime Array(map+vector)

    A. Co-prime Array time limit per test 1 second memory limit per test 256 megabytes input standard in ...

随机推荐

  1. Go HTTP模块处理流程简析

    Go语言提供完善的net/http包,用户使用起来非常方便简单,只需几行代码就可以搭建一个简易的Web服务,可以对Web路由.静态文件.cookie等数据进行操作. 一个使用http包建立的Web服务 ...

  2. js字节转换、字节格式化函数

    有时候在上传附件后需要显示大小,可以选择在后台处理,也可以在前台用js处理. 比如我们想1024MB转换成1GB,那就需要进行转换,这里只是介绍用js进行转换. function bytesToSiz ...

  3. 深入理解PHP7之zval

    PHP7已经发布, 如承诺, 我也要开始这个系列的文章的编写, 今天我想先和大家聊聊zval的变化. 在讲zval变化的之前我们先来看看zval在PHP5下面是什么样子 PHP5zval回顾在PHP5 ...

  4. python__系统 : 线程

    线程之间,全局变量可以共享,但是局部变量依然是不共享的,线程的创建方式: threading.Thread(),还可以定义一个类继承Thread,重写他的run方法,具体和进程的写法一样. 那么,线程 ...

  5. C++基础 对象的管理——单个对象的管理

    1. 为什么要有构造函数和析构函数 面向对象的思想是从生活中来,手机.车出厂时,是一样的. 这些对象都是被初始化后才上市的,初始化是对象普遍存在的一个状态. 普通方案: 对每个类提供一个 init 函 ...

  6. C语言进阶——循环语句07

    循环语句的基本工作方式: 通过条件表达式判定是否执行循环体 条件表达式遵循if语句表达式的原则 do,while,for的区别: do语句先执行后判断,循环体至少执行一次 while语句先判断后执行, ...

  7. PHP代码审计4-漏洞挖掘思路

    漏洞挖掘思路 漏洞形成的条件 1.变量可控制 2.变量可到达有利用价值的函数(危险函数) 漏洞造成的效果 漏洞的利用效果取决于最终的函数功能,变量进入什么样的函数就导致什么样的效果 危险函数 文件包含 ...

  8. struts2官方 中文教程 系列三:使用struts2 标签 tag

    避免被爬,先贴上本帖地址:struts2 官方系列教程一:使用struts2 标签 tag http://www.cnblogs.com/linghaoxinpian/p/6901316.html 本 ...

  9. 通过重写ViewGroup学习onMeasure()和onLayout()方法

    在继承ViewGroup类时,需要重写两个方法,分别是onMeasure和onLayout. 1,在方法onMeasure中调用setMeasuredDimension方法 void android. ...

  10. 《Cracking the Coding Interview》——第14章:Java——题目3

    2014-04-26 18:59 题目:final.finally.finalize有什么区别? 解法:烂大街之java语法题.此题被多少公司考过我不知道,反正我确实遇见过一次了. 代码: // 14 ...