NOI模拟(10.29)T3 颜色

来源:互联网 发布:rimworld mac a14 编辑:程序博客网 时间:2024/05/29 17:20

颜色

题目背景:

10.29 NOI模拟T3

分析:树状数组 + 线段树 + set or 带修莫队 or 分块

 

第一眼带修莫队,思索了一下觉得貌似复杂度真的非常不稳啊······选择另辟蹊径,然后发现了比较稳的树套树做法,首先我们对于每一个位置记录其pre[i],表示上一个出现颜色c[i]的位置是pre[i],那么显然,对于一段区间l ~ r的询问,答案就是所有pre小于l - 1的地方的权值和,这个可以考虑用主席树维护,好了,如果没有修改操作的话,我们就可以用主席树一个log搞过去了,现在考虑修改操作,为了让修改不是nlog,那么我们直接在外层套一个树状数组,这样可以是修改和询问全部变成log2n,然后考虑修改的具体操作,显然我们需要快速查找某一位置的上一个颜色x出现的位置和下一个颜色x的出现位置,我们直接对每一个颜色开一个set,然后每一次lower_bound查询位置即可。

Source:

/*created by scarlyw*/#include <cstdio>#include <string>#include <algorithm>#include <cstring>#include <iostream>#include <cmath>#include <cctype>#include <vector>#include <set>#include <queue>#include <ctime>const int MAXN = 100000 + 10;int n, m, t, x, y, cnt;int c[MAXN], w[MAXN], last[MAXN];std::set<int> color[MAXN];std::set<int> :: iterator it, pre, suc;int root[MAXN];struct node {int left, right, sum;} tree[MAXN * 300];inline void read_in() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i) scanf("%d", &c[i]);for (int i = 1; i <= n; ++i) scanf("%d", &w[i]);}inline void insert(int &cur, int l, int r, int pos, int w) {if (cur == 0) cur = ++cnt;tree[cur].sum += w;if (l == r) return ;int mid = l + r >> 1;if (pos <= mid) insert(tree[cur].left, l, mid, pos, w);else insert(tree[cur].right, mid + 1, r, pos, w);}inline int query(int cur, int l, int r, int ql, int qr) {if (ql <= l && r <= qr) return tree[cur].sum;int mid = l + r >> 1;int ret = 0;if (ql <= mid) ret += query(tree[cur].left, l, mid, ql, qr);if (qr > mid) ret += query(tree[cur].right, mid + 1, r, ql, qr);return ret;}inline int lowbit(int i) {return i & -i;}inline void insert(int i, int pos, int w) {for (; i <= n; i += lowbit(i)) insert(root[i], 0, n, pos, w);}inline void query(int l, int r) {int ans = 0;for (int i = r; i > 0; i -= lowbit(i)) ans += query(root[i], 0, n, 0, l - 1);for (int i = l - 1; i > 0; i -= lowbit(i))ans -= query(root[i], 0, n, 0, l - 1);printf("%d\n", ans);}inline void modify(int pos, int x) {int u = c[pos];if (u == x) return ;it = pre = suc = color[u].lower_bound(pos), pre--, suc++;insert(pos, *pre, -w[u]);if (suc != color[u].end()) insert(*suc, pos, -w[u]), insert(*suc, *pre, w[u]);color[u].erase(it), color[x].insert(pos), c[pos] = x;it = pre = suc = color[x].lower_bound(pos), pre--, suc++;insert(pos, *pre, w[x]);if (suc != color[x].end()) insert(*suc, *pre, -w[x]), insert(*suc, pos, w[x]);}inline void solve_tree() {for (int i = 1; i <= n; ++i) color[i].insert(0);for (int i = 1; i <= n; ++i)color[c[i]].insert(i), insert(i, last[c[i]], w[c[i]]), last[c[i]] = i;}inline void solve_query() {while (m--) {scanf("%d%d%d", &t, &x, &y);if (t == 1) modify(x, y);else query(x, y);}}int main() {freopen("color.in", "r", stdin);freopen("color.out", "w", stdout);read_in();solve_tree();solve_query();return 0;}

原创粉丝点击