题目链接: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 second
struct 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;
}