4447: [Scoi2015]小凸解密码

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 150  Solved: 58
[Submit][Status][Discuss]

Description

小凸得到了一个密码盘,密码盘被等分成N个扇形,每个扇形上有一个数字(0~9),和一个符号(“+”或"*")
密码盘解密的方法如下:
首先,选择一个位置开始,顺时针地将数字和符号分别记在数组A和数组C巾
解密的方法如下
B0=A0
当x>0时:
若Cx为“+”,Bx=(Ax+Ax-1)%10,注意:x-1是下标值
若Cx为“*”,Bx= (Ax×Ax-1)%10,注意:x-1是下标值
操作完成后,可以得到一个长度为n的数组B,然后以B0为起点将B数组顺时针写成一个环,解密就完成
了,称得到的环为答案环。
现在小凸得到了一份指令表,指令表上有2种操作。
一种指令是修改操作,即改变原来密码盘上一个位置的数字和符号。
另一种指令是询问操作,具体如下:
首先从指令给出的位置开始完成解密,得到答案环。
答案环上会有一些0连在一起,将这些连在一起的0称为零区间,找出其中距离B0最远的那个零区间,输
出这个距离。
零区问和B0的距离定义为:零区问内所有0到B0距离中的最小值。

Input

第1行包含2个整数n,m,代表密码盘大小和指令个数
接下来n行,每行包含1个整数和1个字符,按顺时针顺序给出了密码盘上的数组和符号
接下来m行,依次给出指令
每行第1个整数代表指令类型
若第1个墼数为1,代表本行对应指令为修改操作,之后依次有2个整数pos,num和1个字符opt,分别
代表修改的位置,以及修改后该位置的数字和字符
若第1个整数为2,代表本行对应指令位询问操作,之后有1个整数pos,代表本次操作中解密的开始位置
密码盘上的位置标号为0到n-l
数据保证合法,即数据中0≤pos<N,0≤num≤9,opt为“+”或“*”

Output

对于每个询问操作1行,输出答案,若答案环上没有0,输出-1

Sample Input

5 8
0 *
0 *
0 *
0 *
0 *
2 0
1 0 1 +
1 2 1 +
2 3
1 1 1 +
1 3 1 +
1 4 1 +
2 4

Sample Output

0
2
-1

HINT

第1个询问,答案环为[0,0,0,0,0],仅有1个零区间,且B0在其中,所以距离是0
对于第2个询问,答案环为[0,0,1,0,l],有2个零区间,(0,1)和B0距离是o,(3,3)和B0距离是2,故答案为2
对于第3个询问,答案环为[1,2,2,2,2],没有零区间,答案是-1
对于100%数据,5 <=n,m≤10^5
 
 
 
UPDATE:
尴尬地发现其实方法有点小BUG,WA不是因为写错了。
 
错误原因是这样的:
如果区间端点为0,左右区间拼成环后构成新的跨越左右区间的0区间,这时候直接取$min(dis_l,dis_r)$ 不一定是答案,因为有可能左右区间的第二远的0区间比上面取min得到的答案更优,举一个例子:
权值 0 0 0 0 0 1 1 1  0   0   0   1   0   0
位置 1 2 3 4 5 6 8 9 10 11 12 13 14 15
假设查询的是5位置,那么取min得到的答案就是0,而右边区间第二远的0区间的距离是4
 
所以如果出现上述的区间端点为0的情况,就需要查询新的左右区间的最远0区间的距离,即删去跨越左右区间的0区间,再做一次查询最远0区间的操作。
这样做以后虽然复杂度没变,但是常数扩大了很多,不知道能否过掉,有极大可能TLE 几组数据,所以代码就懒得改了
 
 
 
发现了更好的办法
做线段树的时候的时候可以直接维护维护离左右端点最远的和次远0区间的距离
 
下面的blog就是这种做法,可以参照
https://www.cnblogs.com/f321dd/p/6403097.html
 
 
 
以下是原方法
 
 

脑残的 二分+线段树

化环成链,倍增区间

查询的时候分成左右两段区间查询

二分查询每个点最左边的0在哪个位置,最右边的0在哪个位置,用线段树check

找到最左和最右的0之后,线段树查询当前0所在的区间的另一端点,距离为dis

如果两区间不为查询点的端点都为0,那么查询到的最远的0都是端点了。

说明左右区间拼成环之后,可以构成一个新的跨越了左右区间的0区间,答案取$min{(dis_l,dis_r)}$  否则取$max{(dis_l,dis_r)}$

WA + TLE
WA估计是写的时候出了点小错误,不想调试啦。
TLE这东西加点常数优化应该是可以卡过的
好像还有set作法貌似挺简单,直接存全为0的区间即可

  1. #include<bits/stdc++.h>
  2. #define ls u<<1
  3. #define rs ls|1
  4. #define N 200010
  5. using namespace std;
  6. int n,m,a[N],b[N],pd[N<<],lz[N<<],lx[N<<],rx[N<<];char s[N];
  7. void pushup(int u,int l,int r){
  8. int mid=(l+r)>>;
  9. pd[u]=pd[ls]|pd[rs];
  10. lx[u]=lx[ls];rx[u]=rx[rs];
  11. if(lx[u]==mid-l+)lx[u]+=lx[rs];
  12. if(rx[u]==r-mid)rx[u]+=rx[ls];
  13. }
  14. void build(int u,int l,int r){
  15. if(l==r){
  16. if(!b[l])pd[u]=lx[u]=rx[u]=;
  17. else pd[u]=lx[u]=rx[u]=;
  18. return;
  19. }
  20. int mid=(l+r)>>;
  21. build(ls,l,mid);
  22. build(rs,mid+,r);
  23. pushup(u,l,r);
  24. }
  25. void update(int u,int l,int r,int p){
  26. if(l==r){
  27. if(!b[l])pd[u]=lx[u]=rx[u]=;
  28. else pd[u]=lx[u]=rx[u]=;
  29. return;
  30. }
  31. int mid=(l+r)>>;
  32. if(p<=mid)update(ls,l,mid,p);
  33. else update(rs,mid+,r,p);
  34. pushup(u,l,r);
  35. }
  36.  
  37. int query(int u,int L,int R,int l,int r){
  38. if(l<=L&&R<=r)return pd[u];
  39. int mid=(L+R)>>,ret=;
  40. if(l<=mid)ret|=query(ls,L,mid,l,r);
  41. if(r>mid)ret|=query(rs,mid+,R,l,r);
  42. return ret;
  43. }
  44. int asklx(int u,int L,int R,int l,int r){
  45. if(l==L&&R==r)return lx[u];
  46. int mid=(L+R)>>,ret=;
  47. if(r<=mid)return asklx(ls,L,mid,l,r);
  48. if(l>mid)return asklx(rs,mid+,R,l,r);
  49. ret+=asklx(ls,L,mid,l,mid);
  50. if(!ret)return ;
  51. if(ret==mid-l+)ret+=asklx(rs,mid+,R,mid+,r);
  52. return ret;
  53. }
  54. int askrx(int u,int L,int R,int l,int r){
  55. if(l==L&&R==r)return rx[u];
  56. int mid=(L+R)>>,ret=;
  57. if(r<=mid)return askrx(ls,L,mid,l,r);
  58. if(l>mid)return askrx(rs,mid+,R,l,r);
  59. ret+=askrx(rs,mid+,R,mid+,r);
  60. if(!ret)return ;
  61. if(ret==r-mid)ret+=askrx(ls,L,mid,l,mid);
  62. return ret;
  63. }
  64. inline int solve(int x){
  65. static int t1,t2,x1,x2,L,R,l,r;
  66. int mid=(+n)>>;
  67. if(x<mid)x+=n;
  68. L=x-mid+;R=x+mid;
  69. if(!((+n)&))R--;
  70. t1=t2=;
  71. l=x,r=R;
  72. while(l<=r){
  73. mid=(l+r)>>;
  74. if(query(,,n<<,mid,R))t2=mid,l=mid+;
  75. else r=mid-;
  76. }
  77. l=L,r=x;
  78. while(l<=r){
  79. mid=(l+r)>>;
  80. if(query(,,n<<,L,mid))t1=mid,r=mid-;
  81. else l=mid+;
  82. }
  83. if(!t1&&!t2)return -;
  84. if(t1==x&&t2==x)return ;
  85. x1=t1+asklx(,,n<<,t1,x)-;
  86. x2=t2-askrx(,,n<<,x,t2)+;
  87. if(x1==x&&x2==x)return ;
  88. if(t1==L&&t2==R)return min(x2-x,x-x1);
  89. return max(x2-x,x-x1);
  90. }
  91. inline void change(int p,int op){
  92. static int k;k=p-;if(!k)k=n;
  93. if(op)b[p]=(a[k]+a[p])%;
  94. else b[p]=1ll*a[k]*a[p]%;
  95. if(p>n)b[p-n]=b[p];
  96. else b[p+n]=b[p];
  97. }
  98. int main(){
  99. scanf("%d%d",&n,&m);
  100. for(int i=;i<=n;i++)
  101. scanf("%d %c",&a[i],&s[i]);
  102. for(int i=;i<=n;i++){
  103. int j=i-;if(!j)j=n;
  104. if(s[i]=='+')b[i]=(a[i]+a[j])%;
  105. else b[i]=1ll*a[i]*a[j]%;
  106. b[i+n]=b[i];s[i+n]=s[i];a[i+n]=a[i];
  107. }
  108. build(,,n<<);
  109. int x,y,z,p;char op;
  110. while(m--){
  111. scanf("%d%d",&x,&y);++y;
  112. if(x==){
  113. scanf("%d %c",&z,&op);
  114. a[y]=a[y+n]=z;s[y]=s[y+n]=op;
  115. change(y,s[y]=='+'?:);
  116. update(,,n<<,y);
  117. update(,,n<<,y+n);
  118. change(y+,s[y+]=='+'?:);
  119. update(,,n<<,y+);
  120. p=y+>n?y+-n:y++n;
  121. update(,,n<<,p);
  122. }
  123. else printf("%d\n",solve(y));
  124. }
  125. return ;
  126. }

bzoj4447[Scoi2015]小凸解密码的更多相关文章

  1. bzoj4447 SCOI2015 小凸解密码 password

    传送门:bzoj4447 题解: 调试简直恶心,不过调完发现其实还是挺好写的. 用\(\mathrm{set}\)维护一段\(0\)区间的左右端点,每次最多修改两个点,所以很好维护. 查询的时候在\( ...

  2. 2019.03.26 bzoj4447: [Scoi2015]小凸解密码(线段树)

    传送门 题意简述:咕咕咕 思路:考虑预处理出bbb数组,然后每次改动aaa都只会对第iii和i+1i+1i+1这两个位置产生影响,于是可以用线段树来维护bbb数组. 现在求答案的方法是断环为链,倍增整 ...

  3. [bzoj4447] [loj#2010] [Scoi2015] 小凸解密码

    Description 小凸得到了一个密码盘,密码盘被等分成 \(N\) 个扇形,每个扇形上有一个数字(0-9),和一个符号("+"或"*") 密码盘解密的方法 ...

  4. 「SCOI2015」小凸解密码 解题报告

    「SCOI2015」小凸解密码 题意:给一个环,定义一段连续的极长\(0\)串为\(0\)区间,定义一个位置的离一个\(0\)区间的距离为这个位置离这个区间中\(0\)的距离的最小值,每次询问一个位置 ...

  5. bzoj 4447 小凸解密码

    bzoj 4447 小凸解密码 先将原始状态的 \(B\) 处理出来,可以发现,若不修改,则每次指定的起始位置不同,对这个环 \(B\) 带来的影响只有 \(B_0\) 不同,即每次 \(B_0=A_ ...

  6. 【LOJ】#2010. 「SCOI2015」小凸解密码

    题解 断环为链,把链复制两份 用set维护一下全是0的区间,然后查找x + n / 2附近的区间,附近各一个过不去,最后弃疗了改为查附近的两个,然后过掉了= = 熟练掌握stl的应用,你值得拥有(雾 ...

  7. BZOJ_4443_[Scoi2015]小凸玩矩阵_二分+二分图匹配

    BZOJ_4443_[Scoi2015]小凸玩矩阵_二分+二分图匹配 Description 小凸和小方是好朋友,小方给小凸一个N*M(N<=M)的矩阵A,要求小秃从其中选出N个数,其中任意两个 ...

  8. 【BZOJ4445】[Scoi2015]小凸想跑步 半平面交

    [BZOJ4445][Scoi2015]小凸想跑步 Description 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸n边形,N个顶点按照逆时针从0-n-l编号.现 ...

  9. 2018.06.30 BZOJ4443: [Scoi2015]小凸玩矩阵(二分加二分图匹配)

    4443: [Scoi2015]小凸玩矩阵 Time Limit: 10 Sec Memory Limit: 128 MB Description 小凸和小方是好朋友,小方给小凸一个N*M(N< ...

随机推荐

  1. 团队作业7——Beta版本冲刺计划及安排

    上一个阶段的总结: 在Alpha阶段,我们小组已近完成了大部分的功能要求,小组的每一个成员都发挥了自己的用处.经过了这么久的磨合,小组的成员之间越来越默契,相信在接下来的合作中,我们的开发速度会越来越 ...

  2. 在django模板中添加jquery

    路径 /project_name /app_name /templates /index.html /project_name setting.py /static /js jquery.js 导入方 ...

  3. 解决background图片拉伸问题

    ImageView中XML属性src和background的区别: background会根据ImageView组件给定的长宽进行拉伸,而src就存放的是原图的大小,不会进行拉伸.src是图片内容(前 ...

  4. EasyUI 中easyui-textbox和easyui-searchbox文本框的点击事件。

    html: <input id="txtsearch" class="easyui-textbox" data-options="buttonT ...

  5. Python内置函数(50)——issubclass

     英文文档: issubclass(class, classinfo) Return true if class is a subclass (direct, indirect or virtual) ...

  6. React Native学习(九)—— 使用Flexbox布局

    本文基于React Native 0.52 Demo上传到Git了,有需要可以看看,写了新内容会上传的.Git地址 https://github.com/gingerJY/React-Native-D ...

  7. ASP.NET Web API编程——模型验证与绑定

    1.模型验证 使用特性约束模型属性 可以使用System.ComponentModel.DataAnnotations提供的特性来限制模型. 例如,Required特性表示字段值不能为空,Range特 ...

  8. kafka和mqtt的区别是什么?

    两者都是从传统的Pub/Sub消息系统演化出来的,但是进化方向不一样,比较如下: Kafka是为了数据集成的场景,与以往Pub/Sub消息总线不一样,通过分布式架构提供了海量消息处理.高容错的方式存储 ...

  9. 从感知机到 SVM,再到深度学习(一)

        在上篇博客中提到,如果想要拟合一些空间中的点,可以用最小二乘法,最小二乘法其实是以样例点和理论值之间的误差最小作为目标.那么换个场景,如果有两类不同的点,而我们不想要拟合这些点,而是想找到一条 ...

  10. HTML mate标签

    META标签分两大部分:HTTP标题信息(http-equiv)和页面描述信息(name). http-equiv http-equiv类似于HTTP的头部协议,它回应给浏览器一些有用的信息,以帮助正 ...