首先,当发现全场不存在黑色帽子时,显然所有人都知道其是白色帽子,即必然离开

当第一轮时,若第$n$个人发现前面$n-1$个人全是白色时,其自己必然是黑色,必然离开

而第二轮时,若第$n-1$个人发现$n$没有离开,且前面$n-2$个人都是白色时,其自己必然是黑色(否则第$n$个人必然会在第一轮离开),其必然离开

而第三轮时,若第$n-2$个人发现$n$和$n-1$都没有离开,且前面$n-3$个人都是白色时,其自己必然是黑色(否则若第$n-1$个人必然会离开),其必然离开

以此类推,第一个离开的人即第一个黑色的人,假设其编号为$i$,其离开时间即为$n-i$

同时,在$i$之前的人也都知道其为白色,其都会离开

接下来的信息实际上是独立的,即无法利用到前面的信息,换言之会不断重复该过程

(具体的可以类似分析,这里就不再描述了)

例如,当$n=6$且$n$个人颜色依次为0 0 1 0 1 0,离开时间即依次为5 5 4 7 6 7

为了方便,我们需要用更严谨的语言来描述此过程——

令$c_{i}$为第$i$个数的颜色(0或1),$t_{i}$为第$i$个人离开的时间,则有
$$
\begin{cases}t_{i}=\sum_{1\le j\le i,c_{j}=1}n-j+1 & (c_{i}=1)\\t_{i}=t_{nex_{i}}+1&(c_{i}=0)\end{cases}
$$
(其中$nex_{i}$定义为$\min_{i\le j\le n,c_{j}=1}j$,若不存在$j$则定义为$n+1$,且约定$c_{n+1}=1$)

由此,对于$i<j$,若$t_{i}$和$t_{j}$已经确定,根据其关系不难确定一些$c_{i}$,即:

1.若$t_{i}\ge t_{j}+2$,无解(保证有解,即必然不存在此类情况)

2.若$t_{i}=t_{j}+1$,则$c_{j}=1$且$\forall i\le k<j,c_{k}=0$

3.若$t_{i}=t_{j}$,则$\forall i\le k\le j,c_{k}=0$或$\exists i<k<j,c_{k}=1$且$\sum_{k=i}^{n}c_{k}=1$

4.若$t_{i}<t_{j}$,则上述情况都不满足

(注意$t_{n+1}$一定未被确定,因此上述结论成立)

由此,我们将所有非0的$t_{i}$取出,将其划分为若干段单调不上升的连续子序列(假设共$m$段),记其中第$i$段以$t_{l_{i}}$为开头,以$t_{r_{i}}$为结尾,且定义两个参数$R_{i}=nex_{l_{i}}$和$T_{i}=t_{R_{i}}$

当我们确定$R_{i-1}$和$T_{i-1}$后,来考虑$R_{i}$和$T_{i}$(特别的,$R_{0}=T_{0}=0$),分类讨论:

Case 1:$l_{i}<r_{i}$,此时必然有$T_{i}=c_{l_{i}}-1$,继续分类讨论——

Case 1.1:$t_{l_{i}}=t_{r_{i}}+1$,此时根据结论2,有$c_{l_{i}}=c_{l_{i}+1}=...=c_{r_{i}-1}=0$且$c_{r_{i}}=1$,那么不难得到$R_{i}=r_{i}$,此时来构造前面$(R_{i-1},l_{i})$之间1的情况

这些1的目的是保证$T_{i}$的值正确,更具体的,要在$(n-l_{i}+1,n-R_{i-1}]$中选择若干个不同的数(构造),使得其和为$T_{i}-T_{i-1}-(n-R_{i}+1)$(以下该值记作$\Delta_{i}$)

(关于这一类问题,为了不影响分类讨论,在分类讨论结束后再考虑)

Case 1.2:$t_{l_{i}}=t_{r_{i}}$,此时根据结论3,有两种情况,但注意到当第2种情况时,会有$\forall l_{i}\le k\le n,t_{k}\le t_{l_{i}}$,即若是此类情况其必要条件为$i=m$,那么继续分类讨论——

Case 1.2.1:$i<m$,此时根据结论3,有$c_{l_{i}}=c_{l_{i}+1}=...=c_{r_{i}}=0$(因为若是第2种情况,则显然$l_{i}$之后所有数都应该小于等于$t_{l_{i}}$),此时$R_{i}$即在$(r_{i},l_{i+1})$中任选

但当选出$R_{i}$后,我们需要保证可以在$(n-l_{i}+1,n-R_{i-1}]$中选择若干个不同的数,和为$\Delta_{i}$,且对于所有可行的$R_{i}$,可以贪心取其中最小的(即上面的范围扩大)

Case 1.2.2:$i=m$,此时不论$R_{i}$是在$(l_{i},r_{i})$中还是$(r_{i},n+1]$中,都可以令$\forall R_{i}<j\le n,c_{j}=0$(事实上这后面可以任意填,但这里就强制为0了)

$R_{i}$的选择范围是$[l_{i},n+1]$且$t_{R_{i}}\ne 0$,此时在其中找到任意一个合法(可以在$(n-l_{i}+1,n-R_{i}]$选择若干个数和为$\Delta_{i}$)即可

Case 2:$l_{i}=r_{i}$,此时$T_{i}=c_{l_{i}}$或$c_{l_{i}-1}$,且两种情况不像$R_{i}$在多种选择中可以贪心取最小,因此我们使用dp来解决,即用$f_{i,j}$表示$T_{i}=c_{l_{i}}-j$时最小的$R_{i}$,两类转移分类讨论——

Case 2.1:$f_{i,0}$的转移即与Case 1.1相同

Case 2.2:$f_{i,1}$的转移即与Case 1.2相同

(特别的,用$f_{i,j}=-1$表示该类不存在可行的$R_{i}$,那么对于**Case 1**中的情况只需要强制其为-1也可以以此法进行dp)

还需要考虑以下三个未解决的问题:

1.用$[l,r]$中选若干个数和为$x$

2.在$[l,r]$中选若干个数和在$[L,R]$中且尽量小

3.在$[l,r]$中选若干个数和在$S$中($S$为一个集合)

第3个问题由于仅有$i=m$时需要处理,因此可以$o(n)$暴力枚举$S$转换为第1个问题

对于第1个问题,考虑$[l,r]$所能表示的数,虽然并不一定是一个连续区间,但当选择的数个数确定时,一定是一个连续区间

更具体的,假设选择$t$个数($0\le t\le r-l+1$),所能表达的数为$[\sum_{i=l}^{l+t-1}i,\sum_{i=r-t+1}^{r}i]$,显然这个区间的左右端点具有单调性,即可以对$t$二分并判定是否包含

(关于这个区间的正确性,总是存在一个数使得其可以加1来构造即可)

当找到对应一个$t$后,若强制选$l$后,显然之后能覆盖的区间为$[\sum_{i=l}^{l+t-1}i,l+\sum_{i=r-t+2}^{r}i]$,类似地选$r$后能覆盖的区间为$[\sum_{i=l}^{l+t-2}i+r,\sum_{i=r-t+1}^{r}i]$,当$t\ge 2$时两者的并即为原区间

换言之,只需要不断选择$l$或$r$(要判断区间是否仍然包含$x$,总存在一个区间包含$x$)直至$t\le 1$即可

这样的复杂度是$o(r-l)$,在$f_{i,j}$转移时并不需要具体构造出方案,只需要在确定后构造即可,由于$r-l$即所有空隙长度和,总复杂度为$o(n)$

对于第2个问题,只是在转移时求,因此并不需要构造出方案,同样去二分找到第一个与$[L,R]$有公共点的$t$即可处理

综上,总复杂度为$o(n\log n)$,可以通过

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 #define N 200005
  4. 4 #define ll long long
  5. 5 vector<int>v;
  6. 6 int n,m,l[N],r[N],R[N],ans[N],f[N][2],fr[N][2];
  7. 7 ll t[N],T[N];
  8. 8 ll sum(int l,int r){
  9. 9 return 1LL*(l+r)*(r-l+1)/2;
  10. 10 }
  11. 11 ll find(int l,int r,ll L,ll R){
  12. 12 if (L>R)return -1;
  13. 13 int x=0,y=r-l+1;
  14. 14 while (x<y){
  15. 15 int mid=(x+y>>1);
  16. 16 if (sum(r-mid+1,r)>=L)y=mid;
  17. 17 else x=mid+1;
  18. 18 }
  19. 19 if ((sum(r-x+1,r)<L)||(R<sum(l,l+x-1)))return -1;
  20. 20 return max(sum(l,l+x-1),L);
  21. 21 }
  22. 22 void calc(int l,int r,ll k){
  23. 23 int x=0,y=r-l+1;
  24. 24 while (x<y){
  25. 25 int mid=(x+y>>1);
  26. 26 if (sum(r-mid+1,r)>=k)y=mid;
  27. 27 else x=mid+1;
  28. 28 }
  29. 29 if ((sum(r-x+1,r)<k)||(k<sum(l,l+x-1)))assert(0);
  30. 30 while (x>1){
  31. 31 if (k<=l+sum(r-x+2,r)){
  32. 32 k-=l;
  33. 33 ans[n-l+1]=1;
  34. 34 l++;
  35. 35 }
  36. 36 else{
  37. 37 k-=r;
  38. 38 ans[n-r+1]=1;
  39. 39 r--;
  40. 40 }
  41. 41 x--;
  42. 42 }
  43. 43 if (x==1)ans[n-k+1]=1;
  44. 44 }
  45. 45 int main(){
  46. 46 scanf("%d",&n);
  47. 47 for(int i=1;i<=n;i++)scanf("%lld",&t[i]);
  48. 48 for(int i=1;i<=n;i++)
  49. 49 if (t[i]>0)v.push_back(i);
  50. 50 for(int i=0;i<v.size();i++)
  51. 51 if ((!i)||(t[v[i]]>t[v[i-1]])){
  52. 52 if (m)r[m]=v[i-1];
  53. 53 l[++m]=v[i];
  54. 54 }
  55. 55 if (v.size())r[m]=v.back();
  56. 56 l[m+1]=n+1;
  57. 57 f[0][1]=-1;
  58. 58 for(int i=1;i<=m;i++)
  59. 59 for(int j=0;j<2;j++){
  60. 60 f[i][j]=-1;
  61. 61 if ((l[i]<r[i])&&(!j))continue;
  62. 62 ans[0]=ans[1]=-1;
  63. 63 for(int jj=0;jj<2;jj++){
  64. 64 if (f[i-1][jj]<0)continue;
  65. 65 ll delta=(t[l[i]]-j)-(t[l[i-1]]-jj);
  66. 66 if ((t[l[i]]>t[r[i]])||(l[i]==r[i])&&(!j)){
  67. 67 if (find(n-l[i]+2,n-f[i-1][jj],delta-(n-r[i]+1),delta-(n-r[i]+1))>=0)ans[jj]=r[i];
  68. 68 }
  69. 69 else{
  70. 70 if (i==m){
  71. 71 ans[jj]=-1;
  72. 72 for(int k=l[i];k<=n+1;k++)
  73. 73 if ((!t[k])&&(find(n-l[i]+2,n-f[i-1][jj],delta-(n-k+1),delta-(n-k+1))>=0)){
  74. 74 ans[jj]=k;
  75. 75 break;
  76. 76 }
  77. 77 continue;
  78. 78 }
  79. 79 ll s=find(n-l[i]+2,n-f[i-1][jj],delta-(n-r[i]),delta-(n-l[i+1]+2));
  80. 80 if (s>=0)ans[jj]=s-(delta-(n+1));
  81. 81 }
  82. 82 }
  83. 83 if ((ans[0]<0)&&(ans[1]<0))continue;
  84. 84 if ((ans[0]>=0)&&((ans[1]<0)||(ans[0]<ans[1])))fr[i][j]=0;
  85. 85 else fr[i][j]=1;
  86. 86 f[i][j]=ans[fr[i][j]];
  87. 87 }
  88. 88 int lst=-1;
  89. 89 if (f[m][0]>=0)lst=0;
  90. 90 if (f[m][1]>=0)lst=1;
  91. 91 memset(ans,0,sizeof(ans));
  92. 92 for(int i=m;i;i--){
  93. 93 R[i]=f[i][lst];
  94. 94 T[i]=t[l[i]]-lst;
  95. 95 lst=fr[i][lst];
  96. 96 if (R[i]<=n)ans[R[i]]=1;
  97. 97 }
  98. 98 for(int i=1;i<=m;i++)calc(n-l[i]+2,n-R[i-1],T[i]-T[i-1]-(n-R[i]+1));
  99. 99 for(int i=1;i<=n;i++)printf("%d",ans[i]);
  100. 100 }

[cf1349E]Slime and Hats的更多相关文章

  1. 更新lispbox中的ccl和slime版本

    首先C-x C-f然后输入~,找到.emacs文件,根据slime官方文档说明的添加如下代码到文件末尾,重启一下emacs,slime就编译好了,然后这段代码就可以删除.否则每次启动emacs就算不用 ...

  2. Wunder Fund Round 2016 (Div. 1 + Div. 2 combined) A. Slime Combining 水题

    A. Slime Combining 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=2768 Description Your frien ...

  3. 编写php拓展实例--slime项目(用户登录会话类)

      最近公司换了yaf框架,突然对用c实现php拓展感兴趣了,如果一个功能已经很稳定很成熟而且用的地方很多,那么我们就可以尝试用拓展实现(不一定每种情况都可以写成拓展),写成拓展后就不用每次用都包含一 ...

  4. Windows下安装Emacs+Sbcl+Slime

    前言 其实网上已经有很多类似的文章了,我也是按照上面的来做.在做的过程中会遇到几个很坑的地方,我自己也是折腾了好久才弄好.所以现在写出来希望能对大家有所帮助. 正文 下载和安装Emacs http:/ ...

  5. slime+sbcl for common lisp

    sudo apt-get install slime audo apt-get install sbcl ;;sbcl+slime for common lisp ;;sudo apt-get ins ...

  6. Common Lisp学习笔记(0):从SLIME开始 | 优哉·幽斋

    Common Lisp学习笔记(0):从SLIME开始 | 优哉·幽斋 Common Lisp学习笔记(0):从SLIME开始

  7. 在 Emacs 中如何退出 Slime Mode

    1.在 Slime 的 Buffer 中按逗号“,”: 2.在 Command 后输入:sayoonara 3.回车,确认. ================ 退出 SBCL 输入:(sb-ext:q ...

  8. [Codeforces Round #516][Codeforces 1063C/1064E. Dwarves, Hats and Extrasensory Abilities]

    题目链接:1063C - Dwarves, Hats and Extrasensory Abilities/1064E - Dwarves, Hats and Extrasensory Abiliti ...

  9. [CF1038D]Slime

    [CF1038D]Slime 题目大意: 有\(n(n\le5\times10^5)\)只史莱姆,每只史莱姆有一个分数\(w_i(|w_i|le10^9)\),每次一只史莱姆可以吞掉左边的或者右边的史 ...

随机推荐

  1. 理解hashMap

    首先需要理解几个基本概念: 什么是数据结构?(摘自 java数据结构系列--什么是数据结构 (baidu.com)) 数据结构是计算机组织.存储数据的方式.简单来说就是,数据按指定的规则进行存储,从而 ...

  2. MacOS下Java与JDK关系与相关路径

    MacOS下Java与JDK关系与相关路径 macOS下的Java与JDK的路径曾经困扰过我一段时间,今天稍有些忘记,故记下笔记,整理一下.Java与JDK的关系不在本文笔记之内,Javaer常识. ...

  3. IPtable防火墙概念介绍

    1.iptables安全优化 1.不配外网,做代理转发或者防火墙映射 2.并发过大,不建议开启防火墙 2.防火墙的工作流程: 按照配置规则的顺序自上而下,从前到后进行过滤 如果匹配上新规则,表明是阻止 ...

  4. keystore password was incorrect

    一.问题由来 最近在部署后台系统项目的时候,希望给项目增加一些安全措施,在项目中添加了SSL证书,可是在自己添加完该证书后,测试启动项目立马报错. 报错信息如下: org.springframewor ...

  5. Java中JDK、JRE和JVM三者之间有什么区别和联系?Java基础!

    任何语言或软件都需要一个运行环境.正如人想生活在空气中,鱼想生活在水中一样,喜荫植物不能暴露在阳光下,任何物体个体的存在都离不开其所需的环境,编程语言也是一样的. 接下来就详细描述一下Java中JDK ...

  6. (googlechrome)未知错误导致安装失败,如果googlechrome....

    ​https://jingyan.baidu.com/article/ea24bc39ffb699da63b33147.html#5827690-tsina-1-63512-fe183374908e7 ...

  7. noip2017D1T3逛公园(拓扑图上dp,记忆化搜索)

    QWQ前几天才刚刚把这个D1T3写完 看着题解理解了很久,果然我还是太菜了QAQ 题目大意就是 给你一个n个点,m条边的图,保证1能到达n,求从1到n的 (设1到n的最短路长度是d)路径长度在[d,d ...

  8. 半天撸一个简易版mybatis

    为什么需要持久层框架? 首先我们先看看使用原生jdbc存在的问题? public static void main(String[] args) { Connection connection = n ...

  9. 新手小白在github上部署一个项目

    新手小白在github上部署一个项目 一. 注册github账号 github地址:https://www.github.com/ 二.下载安装Git 地址:https://git-scm.com/d ...

  10. 树链剖分好(du)题(liu)选做

    1.luogu P4315 月下"毛景树" 题目链接 前言: 这大概是本蒟蒻A掉的题里面码量最大的一道题了.我自认为码风比较紧凑,但还是写了175行. 从下午2点多调到晚上8点.中 ...