这道题很明显使用线段树来做。
我们让线段树维护b
对于修改操作,我们只需要修改四个点
对于查询操作,可以想到二分答案,我们把b复制一倍放在末尾,只需要判断[x+mid,x+n-mid]中是否有一段被大于0的数包围的一串0,因为要考虑边界问题,所以把判断的区间改成[x+mid-1,x+n-mid+1]更加便于维护和查找
#include
#include
#include
#include
#include
using namespace std;
template<typename T>inline void read(T &x) {
x = 0; int f = 0; char s = getchar();
while (!isdigit(s)) f |= s=='-', s = getchar();
while ( isdigit(s)) x = x * 10 + s - 48, s = getchar();
x = f ? -x : x;
}
int ss = 0, buf[31];
template<typename T>inline void print(T x) {
if (x < 0) putchar('-'), x = -x;
do {buf[++ss] = int(x % 10); x /= 10;} while(x);
while (ss) putchar(buf[ss--] + '0'); puts("");
}
const int N = 2e5 + 6;
char s[5];
int n, q, a[N], c[N];
struct T {
int l, r, c, s;
void init(int v) {
s = 0;
if (v) l = r = c = 1;
else l = r = c = 0;
}
} t[N << 2];
T operator + (const T &a, const T &b) {
T c;
c.l = a.l, c.r = b.r;
c.c = a.c + b.c, c.s = a.s + b.s;
if (a.c && b.c && (!a.r || !b.l)) ++c.s;
return c;
}
void Modify(int p, int l, int r, int x, int v) {
if (l == r) { t[p].init(v); return;}
int mid = (l + r) >> 1;
if (x <= mid) Modify(p << 1, l, mid, x, v);
else Modify(p << 1 | 1, mid + 1, r, x, v);
t[p] = t[p << 1] + t[p << 1 | 1];
}
T Query(int p, int l, int r, int L, int R) {
if (L <= l && r <= R) return t[p];
int mid = (l + r) >> 1;
if (R <= mid) return Query(p << 1, l, mid, L, R);
else if (mid < L) return Query(p << 1 | 1, mid + 1, r, L, R);
else return Query(p << 1, l, mid, L, R) + Query(p << 1 | 1, mid + 1, r, L, R);
}
int Calc(int i) {
return c[i] ? a[i] * a[i - 1] % 10 : (a[i] + a[i - 1]) % 10;
}
int main() {
read(n), read(q);
for (int i = 1; i <= n; i++) {
read(a[i]); scanf("%s", s); c[i] = (s[0] == '*');
a[n + i] = a[i], c[n + i] = c[i];
}
for (int i = 2; i <= (n << 1); i++)
Modify(1, 1, n << 1, i, Calc(i));
int op, x;
while (q--) {
read(op), read(x); ++x;
if (op == 1) {
read(a[x]); scanf("%s", s); c[x] = (s[0] == '*');
a[n + x] = a[x], c[n + x] = c[x];
if (x > 1) Modify(1, 1, n << 1, x, Calc(x));
Modify(1, 1, n << 1, x + 1, Calc(x + 1));
Modify(1, 1, n << 1, x + n, Calc(x + n));
if (x < n) Modify(1, 1, n << 1, n + x + 1, Calc(x + n + 1));
}
else {
if (!a[x] && Query(1, 1, n << 1, x + 1, n + x - 1).s == 0) { puts("0"); continue;}
Modify(1, 1, n << 1, x, a[x]);
Modify(1, 1, n << 1, n + x, a[x]);
int l = 0, r = n >> 1, mid, ans = -2;
while (l <= r) {
mid = (l + r) >> 1;
if (Query(1, 1, n << 1, x + mid, n + x - mid).s) ans = mid, l = mid + 1;
else r = mid - 1;
}
++ans; print(ans);
if (x > 1) Modify(1, 1, n << 1, x, Calc(x));
Modify(1, 1, n << 1, n + x, Calc(n + x));
}
}
return 0;
}