题目
Luogu
LOJ
Acwing
思路
代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 200010;
int n, m, A[N], B[N];
char C[N];
struct NODE { int l, r, a, b, s, c; } tr[N << 2];
inline void init(int u, int c) {
if (c == 0) tr[u].a = tr[u].b = tr[u].c = tr[u].s = 0;
else tr[u].a = tr[u].b = tr[u].c = 1, tr[u].s = 0;
}
inline NODE operator+(const NODE &l, const NODE &r) { // 运算符重载
NODE u = (NODE) { l.l, r.r };
u.c = l.c + r.c, u.s = l.s + r.s;
u.a = l.a, u.b = r.b;
if (l.c && r.c && (!l.b || !r.a)) u.s++;
return u;
}
void build(int u, int l, int r) {
tr[u].l = l, tr[u].r = r;
if (l == r) return init(u, B[l]), void(0);
int mid = (l + r) >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
tr[u] = tr[u << 1] + tr[u << 1 | 1];
}
void modify(int u, int x, int c) {
if (tr[u].l == tr[u].r) return init(u, c), void(0);
int mid = (tr[u].l + tr[u].r) >> 1;
if (x <= mid) modify(u << 1, x, c);
else modify(u << 1 | 1, x, c);
tr[u] = tr[u << 1] + tr[u << 1 | 1];
}
NODE query(int u, int l, int r) {
if (l <= tr[u].l && tr[u].r <= r) return tr[u];
int md = (tr[u].l + tr[u].r) >> 1;
if (r <= md) return query(u << 1, l, r);
else if (l > md) return query(u << 1 | 1, l, r);
else return query(u << 1, l, r) + query(u << 1 | 1, l, r); // 注意讨论
}
int calc(int x) { return ((C[x] == '+') ? (A[x] + A[x - 1]) : (A[x] * A[x - 1])) % 10; }
inline void modify(int pos, int num, char opt) {
A[pos] = A[pos + n] = num, C[pos] = C[pos + n] = opt;
if (pos > 1) modify(1, pos, calc(pos)); // 如果是开头, 不用计算
modify(1, pos + n, calc(pos + n));
modify(1, pos + 1, calc(pos + 1));
if (pos < n) modify(1, pos + n + 1, calc(pos + n + 1)); // n + pos + 1 超出长度, 不用算
}
bool check(int mid, int pos) { return query(1, pos + mid, n + pos - mid).s; }
inline int query(int pos) {
// 这两行注释了也能过, 样例都过不了......
if (A[pos] == 0 && query(1, pos + 1, pos + n - 1).s == 0) return 0; // 特判 0
if (query(1, pos, pos + n).s == 0) return -1; // 特判 -1
modify(1, pos, A[pos]), modify(1, pos + n, A[pos]);
int l = 0, r = n >> 1;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (query(1, pos + mid, n + pos - mid).s) l = mid;
else r = mid - 1;
}
if (pos > 1) modify(1, pos, calc(pos));
modify(1, pos + n, calc(pos + n));
return l + 1; // 注意加 1
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> A[i] >> C[i];
for (int i = 1; i <= n; i++) A[i + n] = A[i], C[i + n] = C[i];
for (int i = 2; i <= n << 1; i++) B[i] = calc(i);
build(1, 1, n << 1);
char opt;
for (int op, pos, num; m-- && cin >> op >> pos; ) // 由于从 1 开始, 下标需要加 1
if (op == 2) cout << query(pos + 1) << endl;
else cin >> num >> opt, modify(pos + 1, num, opt);
return 0;
}