考虑对于一个给定的颜色集合 \(S\),我们可达的位置一定是一个区间 \([L,R]\)。于是考虑怎么求出 \(L,R\) 即可。
考虑二分,现在问题转换成判定一个区间 \([x,R]\)(区间 \([L,x]\) 同理)是否所有颜色都在我们的集合 \(S\) 中。
考虑对每一个颜色开一个线段树。区间 \([x,R]\) 里的每个颜色都在集合 \(S\) 中,等价于 \(S\) 中所有颜色在 \([x,R]\) 里的出现次数之和为 \(R-x+1\)。
时间复杂度 \(O(n\log^2 n)\),如果实现的精细一点用线段树上二分可以做到 \(O(n \log n)\)。
const int MAXN = 1e5 + 5;
int n, q, c[MAXN], v[MAXN];struct _sgt {struct _node {int v, ls, rs;} tr[MAXN << 6];int tot;void pushup(int p) {tr[p].v = tr[tr[p].ls].v + tr[tr[p].rs].v;}void modify(int &p, int l, int r, int k, int v) {if (!p) p = ++tot;if (l == r) return tr[p].v += v, void();if (k <= mid) modify(tr[p].ls, l, mid, k, v);else modify(tr[p].rs, mid + 1, r, k, v);pushup(p);}int query(int p, int l, int r, int L, int R) {if (!p) return 0;if (L <= l && r <= R) return tr[p].v;int res = 0;if (L <= mid) res += query(tr[p].ls, l, mid, L, R);if (mid < R) res += query(tr[p].rs, mid + 1, r, L, R);return res;}void clear(int p) {if (tr[p].ls) clear(tr[p].ls);if (tr[p].rs) clear(tr[p].rs);tr[p].v = tr[p].ls = tr[p].rs = 0;}
} t;
int rt[MAXN];int solveR(int x, int k, vector<int> a) {int l = x, r = n + 1;while (l + 1 < r) {int sum = 0;for (int i = 0; i < k; ++i)sum += t.query(rt[a[i]], 1, n, x, mid);if (sum == (mid - x + 1)) l = mid;else r = mid;}return l;
}int solveL(int x, int k, vector<int> a) {int l = 0, r = x;while (l + 1 < r) {int sum = 0;for (int i = 0; i < k; ++i)sum += t.query(rt[a[i]], 1, n, mid, x);if (sum == (x - mid + 1)) r = mid;else l = mid;}return r;
}struct _bit {int tr[MAXN];int lowbit(int x) { return x & (-x); }void modify(int x, int v) {while (x <= n) {tr[x] += v;x += lowbit(x);}}int query(int x) {int res = 0;while (x) {res += tr[x];x -= lowbit(x);}return res;}
} bit;void work() {cin >> n >> q;for (int i = 1; i <= n; ++i)cin >> c[i];for (int i = 1; i <= n; ++i)cin >> v[i];for (int i = 1; i <= n; ++i) {t.modify(rt[c[i]], 1, n, i, 1);bit.modify(i, v[i]);}while (q--) {int op; cin >> op;if (op == 1) {int p, x; cin >> p >> x;t.modify(rt[c[p]], 1, n, p, -1);t.modify(rt[x], 1, n, p, 1);c[p] = x;} else if (op == 2) {int p, x; cin >> p >> x;bit.modify(p, x - v[p]);v[p] = x;} else {int x, k; cin >> x >> k;vector<int> a(k);for (int i = 0; i < k; ++i)cin >> a[i];int L = solveL(x, k, a), R = solveR(x, k, a);cout << bit.query(R) - bit.query(L - 1) << endl;}}for (int i = 1; i <= n; ++i) {t.clear(rt[i]);bit.tr[i] = 0;}fill(rt, rt + 1 + n, 0ll);t.tot = 0;
}