解题报告 『矿洞:坍塌(ODT)』
退役第二天也要坚持用珂朵莉树水题。
代码实现如下:
#include <bits/stdc++.h> using namespace std; #define IT set<node>::iterator #define rep(i, a, b) for (register int i = (a); i <= (b); i++) const int maxn = 5e5 + 5; int n, m, cnt = 1; char str[maxn]; struct node { int l, r; mutable char v; node(int L, int R = -1, char V = 0): l(L), r(R), v(V) {} int operator <(const node &o) const { return l < o.l; } }; set<node> s; int read() { int x = 0, flag = 0; char ch = ' '; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') { flag = 1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ '0'); ch = getchar(); } return flag ? -x : x; } IT split(int pos) { IT it = s.lower_bound(node(pos)); if (it != s.end() && it->l == pos) return it; it--; int L = it->l, R = it->r; char V = it->v; s.erase(it); s.insert(node(L, pos - 1, V)); return s.insert(node(pos, R, V)).first; } void assign(int l, int r, char val) { IT itr = split(r + 1), itl = split(l); s.erase(itl, itr); s.insert(node(l, r, val)); } char get_val(int pos) { IT it = split(pos); return it->v; } int check(int l, int r) { IT itr = split(r + 1), itl = split(l); char now = itl->v; while (itl != itr) { if (now != itl->v) return 0; itl++; } return 1; } int main() { n = read(); scanf("%s", str + 1); char pre = str[1]; rep(i, 2, n) { if (pre == str[i]) cnt++; else { s.insert(node(i - cnt, i - 1, pre)); cnt = 1; pre = str[i]; } } s.insert(node(n - cnt + 1, n, pre)); m = read(); char tmp[3]; rep(i, 1, m) { int l, r; scanf("%s", tmp + 1), l = read(), r = read(); if (tmp[1] == 'A') { char opt[3]; scanf("%s", opt + 1); assign(l, r, opt[1]); } else { if (l == 1 || l == n || r == 1 || r == n) { if (check(l, r)) printf("Yes\n"); else printf("No\n"); continue; } char a = get_val(l - 1), b = get_val(r + 1); if (a == b || !check(l, r)) printf("No\n"); else printf("Yes\n"); } } return 0; }
ODT并不是这道题的正解,所以不开O2的话只有90pts(当然也有可能是我太蒻了)。
线段树的做法有时间再写吧。