Loj2010「SCOI2015」小凸解密碼

這道題很明顯使用線段樹來做。
我們讓線段樹維護b
對於修改操作,我們只需要修改四個點
對於查詢操作,可以想到二分答案,我們把b複製一倍放在末尾,只需要判斷[x+mid,x+n-mid]中是否有一段被大於0的數包圍的一串0,因爲要考慮邊界問題,所以把判斷的區間改成[x+mid-1,x+n-mid+1]更加便於維護和查找

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章