uva 12345 (分段 / 树套树(好题))

来源:互联网 发布:淘宝客怎么注册买家 编辑:程序博客网 时间:2024/05/17 14:18

题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3767

开通博客的第一篇解题报告, 题目要求维护一个序列支持两种操作1. 序列的单点修改 2.查询序列区间内不同的数的个数。 本题有很多解法我打算就写下列三种: 1.分段  2.线段树套Treap 3.树状数组套主席树, 题目中的查询不好处理, 我们可以考虑把原数组转化一下, 令arr表示原数组, 定义 L数组 L[i] = max{j | j < i && A[j] = A[i]} 其实就是i左边第一个等于arr[i]的下标, 这样对于区间[l, r]的查询就变成查询数组L的区间[l, r]中有多少小于l的数字。

1.分段(Rank3!!)

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>#include <vector>#include <map>#include <set>#include <queue>using namespace std;const int sz = 400;struct Block {int A[605][sz + 1], B[605][sz + 1];int size[605];int n, row;void init(int n, int* L) {this->n = n;row = 0;memset(size, 0, sizeof(size));int r = 0, c = 0;for (int i = 0; i < n; i++) {A[r][c] = L[i];B[r][c] = A[r][c];size[r]++;c++;if (c == sz) {c = 0;r++;}}row = r + 1;for (int i = 0; i < row; i++)sort(B[i], B[i] + size[i]);}void modify(int p, int val) {int r = p / sz, c = p % sz;if (A[r][c] == val) return;int old = A[r][c];A[r][c] = val;int pos = lower_bound(B[r], B[r] + size[r], old) - B[r];B[r][pos] = val;if (val > old) {while (pos < size[r] - 1 && B[r][pos + 1] < B[r][pos]) {swap(B[r][pos], B[r][pos + 1]);pos++;}}else {while (pos > 0 && B[r][pos - 1] > B[r][pos]) {swap(B[r][pos], B[r][pos - 1]);pos--;}}}int query(int l, int r, int x) {if (r < l) return 0;int r1 = l / sz, r2 = r / sz;int c1 = l % sz, c2 = r % sz;int res = 0;if (r1 == r2) {while (c1 <= c2) {if (A[r1][c1] < x) res++;c1++;}}else {int tmp = size[r1];while (c1 < tmp) {if (A[r1][c1] < x) res++;c1++;}r1++;while (c2 >= 0) {if (A[r2][c2] < x) res++;c2--;}while (r1 < r2) {res += lower_bound(B[r1], B[r1] + size[r1], x) - B[r1];r1++;}}return res;}}key;const int N = 100005;#define fi first#define se secondstruct Solve {int L[N], arr[N];map<int, set<int> > Map;map<int, set<int> >::iterator it1;set<int>::iterator it2;int n;void init(int n) {this->n = n;Map.clear();for (int i = 0; i < n; i++) {scanf("%d", &arr[i]);if (Map.find(arr[i]) == Map.end()) {Map[arr[i]].insert(-1);Map[arr[i]].insert(n);}Map[arr[i]].insert(i);it2 = Map[arr[i]].lower_bound(i);it2--;L[i] = *(it2);}key.init(n, L);}void modify(int p, int x) {if (arr[p] == x) return;int old = arr[p];arr[p] = x;Map[old].erase(p);int p2 = *(Map[old].upper_bound(p));if (p2 != n) {it2 = Map[old].lower_bound(p);it2--;L[p2] = *(it2);key.modify(p2, L[p2]);}if (Map.find(x) == Map.end()) {Map[x].insert(-1);Map[x].insert(n);}Map[x].insert(p);p2 = *(Map[x].upper_bound(p));if (p2 != n) {L[p2] = p;key.modify(p2, p);}it2 = Map[x].lower_bound(p);it2--;L[p] = *(it2);key.modify(p, L[p]);}int query(int l, int r) {return key.query(l, r, l);}}sol;int main() {int n, m, p, x, l, r;char op[3];scanf("%d%d", &n, &m);sol.init(n);for (int i = 0; i < m; i++) {scanf("%s", op);if (op[0] == 'Q') {scanf("%d%d", &l, &r);printf("%d\n", sol.query(l, r - 1));}else {scanf("%d%d", &p, &x);sol.modify(p, x);}}return 0;}

原创粉丝点击