码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj4447[Scoi2015]小凸解密码

时间:2018-01-21 19:17:49      阅读:308      评论:0      收藏:0      [点我收藏+]

标签:估计   最小   rip   线段树   mes   一个   bzoj   max   大小   

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
 

脑残的 二分+线段树
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<<2],lz[N<<2],lx[N<<2],rx[N<<2];char s[N];
  7 void pushup(int u,int l,int r){
  8     int mid=(l+r)>>1;
  9     pd[u]=pd[ls]|pd[rs];
 10     lx[u]=lx[ls];rx[u]=rx[rs];
 11     if(lx[u]==mid-l+1)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]=1;
 17         else pd[u]=lx[u]=rx[u]=0;
 18         return;
 19     }
 20     int mid=(l+r)>>1;
 21     build(ls,l,mid);
 22     build(rs,mid+1,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]=1;
 28         else pd[u]=lx[u]=rx[u]=0;
 29         return;
 30     }
 31     int mid=(l+r)>>1;
 32     if(p<=mid)update(ls,l,mid,p);
 33     else update(rs,mid+1,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)>>1,ret=0;
 40     if(l<=mid)ret|=query(ls,L,mid,l,r);
 41     if(r>mid)ret|=query(rs,mid+1,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)>>1,ret=0;
 47     if(r<=mid)return asklx(ls,L,mid,l,r);
 48     if(l>mid)return asklx(rs,mid+1,R,l,r);
 49     ret+=asklx(ls,L,mid,l,mid);
 50     if(!ret)return 0;
 51     if(ret==mid-l+1)ret+=asklx(rs,mid+1,R,mid+1,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)>>1,ret=0;
 57     if(r<=mid)return askrx(ls,L,mid,l,r);
 58     if(l>mid)return askrx(rs,mid+1,R,l,r);
 59     ret+=askrx(rs,mid+1,R,mid+1,r);
 60     if(!ret)return 0;
 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=(1+n)>>1;
 67     if(x<mid)x+=n;
 68     L=x-mid+1;R=x+mid;
 69     if(!((1+n)&1))R--;
 70     t1=t2=0;
 71     l=x,r=R;
 72     while(l<=r){
 73         mid=(l+r)>>1;
 74         if(query(1,1,n<<1,mid,R))t2=mid,l=mid+1;
 75         else r=mid-1;
 76     }
 77     l=L,r=x;
 78     while(l<=r){
 79         mid=(l+r)>>1;
 80         if(query(1,1,n<<1,L,mid))t1=mid,r=mid-1;
 81         else l=mid+1;
 82     }
 83     if(!t1&&!t2)return -1;
 84     if(t1==x&&t2==x)return 0;
 85     x1=t1+asklx(1,1,n<<1,t1,x)-1;
 86     x2=t2-askrx(1,1,n<<1,x,t2)+1;
 87     if(x1==x&&x2==x)return 0;
 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-1;if(!k)k=n;
 93     if(op)b[p]=(a[k]+a[p])%10;
 94     else b[p]=1ll*a[k]*a[p]%10;
 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=1;i<=n;i++)
101     scanf("%d %c",&a[i],&s[i]);
102     for(int i=1;i<=n;i++){
103         int j=i-1;if(!j)j=n;
104         if(s[i]==+)b[i]=(a[i]+a[j])%10;
105         else b[i]=1ll*a[i]*a[j]%10;
106         b[i+n]=b[i];s[i+n]=s[i];a[i+n]=a[i];
107     }
108     build(1,1,n<<1);
109     int x,y,z,p;char op;
110     while(m--){
111         scanf("%d%d",&x,&y);++y;
112         if(x==1){
113             scanf("%d %c",&z,&op);
114             a[y]=a[y+n]=z;s[y]=s[y+n]=op;
115             change(y,s[y]==+?1:0);
116             update(1,1,n<<1,y);
117             update(1,1,n<<1,y+n);
118             change(y+1,s[y+1]==+?1:0);
119             update(1,1,n<<1,y+1);
120             p=y+1>n?y+1-n:y+1+n;
121             update(1,1,n<<1,p);
122         }
123         else printf("%d\n",solve(y));
124     }
125     return 0;
126 }

 

bzoj4447[Scoi2015]小凸解密码

标签:估计   最小   rip   线段树   mes   一个   bzoj   max   大小   

原文地址:https://www.cnblogs.com/wsy01/p/8324760.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!