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
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
解题思路:
先预处理出所有b[i]的值,那么修改就会改变b[i]和b[i+1],询问相当于把b[i]变成a[i]。
用set维护一下0区间,每次找pos+n/2旁边的几个区间计算距离取max即可。
#include<bits/stdc++.h>
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c!='-')&&(c<'0'||c>'9');c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=100005;
int n,m,a[N],b[N],c[N],cnt;
struct node
{
int l,r;
node(int _l=0,int _r=0):l(_l),r(_r){};
inline friend bool operator < (const node &a,const node &b)
{return a.l<b.l;}
};
set<node>S;
#define It set<node>::iterator
inline int nxt(int i){return i==n?1:i+1;}
inline int bef(int i){return i==1?n:i-1;}
inline It Nxt(It it){return it==--(--S.end())||it==--S.end()?++S.begin():++it;}
inline It Bef(It it){return it==++S.begin()||it==S.begin()?--(--S.end()):--it;}
It it;
void Insert(int p)
{
node t=node(p,p),suf,pre;
it=S.lower_bound(t),suf=*it;
if(suf.l!=n+1&&suf.l==p+1)S.erase(it),t.r=suf.r;
it=--S.lower_bound(t),pre=*it;
if(pre.r&&pre.r==p-1)S.erase(it),t.l=pre.l;
S.insert(t);
}
void Delete(int p)
{
node t=node(p,p),cur;
it=--S.upper_bound(t),cur=*it,S.erase(it);
if(cur.l<p)S.insert(node(cur.l,p-1));
if(cur.r>p)S.insert(node(p+1,cur.r));
}
void modify(int p,int x,int y)
{
if(x&&!y)Insert(p);
if(!x&&y)Delete(p);
}
bool in(int l,int r,int p)
{
if(l<=r)return l<=p&&p<=r;
else return l<=p||p<=r;
}
int calc(int l,int r,int p)
{
if(in(l,r,p))return 0;
return min(min(abs(p-l),abs(p-r)),min(n-abs(p-r),n-abs(p-l)));
}
int solve(node tmp,int p)
{
if(tmp.l==1)
{
node t=*--(--S.end());
if(t.r==n)tmp.l=t.l;
}
if(tmp.r==n)
{
node t=*++S.begin();
if(t.l==1)tmp.r=t.r;
}
return calc(tmp.l,tmp.r,p);
}
int query(int p)
{
if(S.size()==2)return -1;
int pos=p+n/2;if(pos>n)pos-=n;
node t=node(pos,pos),suf,pre;
it=S.lower_bound(t);
int res=0;
it=Bef(Bef(Bef(it)));
for(int i=1;i<=6;i++)
res=max(res,solve(*it,p)),it=Nxt(it);
return res;
}
int main()
{
//freopen("lx.in","r",stdin);
//freopen("lx.out","w",stdout);
n=getint(),m=getint();
for(int i=1;i<=n;i++)a[i]=getint(),c[i]=(getchar()=='+'?0:1);
for(int i=1;i<=n;i++)b[i]=(c[i]?a[bef(i)]*a[i]%10:(a[bef(i)]+a[i])%10);
S.insert(node(0,0)),S.insert(node(n+1,n+1));
for(int i=1;i<=n;i++)if(!b[i])Insert(i);
while(m--)
{
int op=getint(),p=getint()+1,x=0,y=0;
if(op==1)
{
a[p]=getint(),c[p]=(getchar()=='+'?0:1);
x=b[p],y=b[p]=(c[p]?a[bef(p)]*a[p]%10:(a[bef(p)]+a[p])%10);
modify(p,x,y);
x=b[nxt(p)],y=b[nxt(p)]=(c[nxt(p)]?a[p]*a[nxt(p)]%10:(a[p]+a[nxt(p)])%10);
modify(nxt(p),x,y);
}
else
{
modify(p,b[p],a[p]);
printf("%d\n",query(p));
modify(p,a[p],b[p]);
}
}
return 0;
}