[关闭]
@ysner 2018-08-20T15:23:36.000000Z 字数 1485 阅读 2137

[CF1023D]Array Restoration

set


题面

有长度为的数列。有次操作。
次操作中,必须把中所有数字改为
现在给出疑似最终数列,其中几个数被改成了。回答是否存在初始数列。

解析

很显然的是,如果两个相同数之间存在比它们小的数,这个序列一定不合法。
同样,如果这个序列不存在值为的数,这个序列也不合法。

思考怎么填数。
首先,如果没有数列中没有数字,优先填
其次,设数分别在该位左右两边存在,则该位应取
再次,如果不存在,该位填。(因为绝对合法,且不可能干扰到其它位的填数)

然后想怎么维护这个
考虑弄个维护,所有的第一个出现时,;所有的最后一个出现时,
可删除大根堆也可以,只是写着麻烦。

还有,取中最后一个数可以用*--Q.end(),end不会真的自减。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<cmath>
  6. #include<algorithm>
  7. #include<vector>
  8. #include<set>
  9. #define re register
  10. #define il inline
  11. #define ll long long
  12. #define max(a,b) ((a)>(b)?(a):(b))
  13. #define min(a,b) ((a)<(b)?(a):(b))
  14. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  15. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  16. using namespace std;
  17. const int mod=45989,N=5e5+100;
  18. int n,m,top,a[N],L[N],R[N],mx,mn;
  19. set<int>Q;
  20. set<int>::iterator it;
  21. il int gi()
  22. {
  23. re int x=0,t=1;
  24. re char ch=getchar();
  25. while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
  26. if(ch=='-') t=-1,ch=getchar();
  27. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  28. return x*t;
  29. }
  30. int main()
  31. {
  32. n=gi();m=gi();
  33. fp(i,1,n) a[i]=gi(),mx=max(mx,a[i]),mn=min(mn,a[i]);
  34. fq(i,n,1) if(!R[a[i]]) R[a[i]]=i;
  35. fp(i,1,n) if(!L[a[i]]) L[a[i]]=i;
  36. fp(i,1,n)
  37. {
  38. if(a[i]==0)
  39. {
  40. if(mx<m) a[i]=m,mx=m;
  41. else if(Q.size()) a[i]=*--Q.end();
  42. else a[i]=1;
  43. }
  44. else
  45. {
  46. if(L[a[i]]==i&&L[a[i]]<R[a[i]]) Q.insert(a[i]);
  47. if(R[a[i]]==i&&L[a[i]]<R[a[i]]) Q.erase(a[i]);
  48. if(Q.size()) if(a[i]<(*--Q.end())) {puts("NO");return 0;}
  49. }
  50. }
  51. if(mx<m) {puts("NO");return 0;}
  52. puts("YES");
  53. fp(i,1,n) printf("%d ",a[i]);puts("");
  54. return 0;
  55. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注