http://www.spoj.pl/problems/RACETIME/
题意:1、修改某个数;2、求区间内小于等于某个数的数有多少个。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 100010;
struct Node {
int key, val;
Node(){};
Node(int a, int b) { key = a; val = b; }
bool operator < (Node b) { return val < b.val; }
bool operator <= (Node b) { return val <= b.val; }
bool operator > (Node b) { return val > b.val; }
bool operator >= (Node b) { return val >= b.val; }
bool operator == (Node b) { return val == b.val; }
Node operator + (int a) {
return Node(key, val+a) > Node(key, val) ? Node(key, val+a) : Node(key, val-a);
}
};
int sz[maxn*30];
int key[maxn*30];
int lch[maxn*30];
int rch[maxn*30];
int tot;
template<typename Type>
class SBT
{
public:
SBT() { Clear(); }
void Clear() { root = 0; lch[0] = rch[0] = sz[0] = 0; }
static void ClearAll() { tot = 0; }
int Size() { return sz[root]; }
bool Empty() { return 0 == sz[root]; }
bool Find(Type k) { return Find(root, k); }
void InsertR(Type k) { Insert(root, k); } // 可重复插入
void Insert(Type k) { if (!Find(k)) Insert(root, k); }
void Delete(Type k) { if (Find(k)) Delete(root, k); }
void DeleteSmaller(Type k) { DeleteSmaller(root, k); }
int GetRank(Type k) { return GetRank(root, k); }
Type GetKth(int k) { return GetKth(root, k); }
Type GetMin() { return GetKth(root, 1); }
Type GetMax() { return GetKth(root, Size()); }
Type GetPre(Type k) { return GetPre(root, k); }
Type GetSuc(Type k) { return GetSuc(root, k); }
int GetSmaller(Type k) { return GetSmaller(root, k); } // 返回小于k的元素的个数
private:
void LeftRotate(int &t) {
int k = rch[t];
rch[t] = lch[k];
lch[k] = t;
sz[k] = sz[t];
sz[t] = 1 + sz[lch[t]] + sz[rch[t]];
t = k;
}
void RightRotate(int &t) {
int k = lch[t];
lch[t] = rch[k];
rch[k] = t;
sz[k] = sz[t];
sz[t] = 1 + sz[lch[t]] + sz[rch[t]];
t = k;
}
void Maintain(int &t, bool flag) {
if (0 == t) return ;
if (false == flag) {
if (sz[lch[lch[t]]] > sz[rch[t]]) {
RightRotate(t);
} else if (sz[rch[lch[t]]] > sz[rch[t]]) {
LeftRotate(lch[t]);
RightRotate(t);
} else {
return ;
}
} else {
if (sz[rch[rch[t]]] > sz[lch[t]]) {
LeftRotate(t);
} else if (sz[lch[rch[t]]] > sz[lch[t]]) {
RightRotate(rch[t]);
LeftRotate(t);
} else {
return ;
}
}
Maintain(lch[t], false);
Maintain(rch[t], true);
Maintain(t, false);
Maintain(t, true);
}
Type GetPre(int t, Type k) {
if (0 == k) return k;
if (k <= key[t]) return GetPre(lch[t], k);
Type tmp = GetPre(rch[t], k);
if (tmp == k) return key[t];
return tmp;
}
Type GetSuc(int t, Type k) {
if (0 == root) return k;
if (k >= key[t]) return GetSuc(rch[t], k);
Type tmp = GetSuc(lch[t], k);
if (tmp == k) return key[t];
return tmp;
}
Type GetKth(int t, int k) {
if (sz[lch[t]] >= k) return GetKth(lch[t], k);
if (sz[lch[t]] == k - 1) return key[t];
return GetKth(rch[t], k - sz[lch[t]] - 1);
}
int GetRank(int t, Type k) {
if (0 == t) return 0;
if (k < key[t]) return GetRank(lch[t], k);
return sz[lch[t]] + 1 + GetRank(rch[t], k);
}
int GetSmaller(int t, Type k) {
if (0 == t) return 0;
if (k <= key[t]) return GetSmaller(lch[t], k);
return sz[lch[t]] + 1 + GetSmaller(rch[t], k);
}
bool Find(int t, Type k) {
if (0 == t) return false;
else if (k < key[t]) return Find(lch[t], k);
else return (key[t] == k || Find(rch[t], k));
}
void Insert(int &t, Type k) {
if (0 == t) {
t = ++tot;
lch[t] = rch[t] = 0;
sz[t]= 1;
key[t] = k;
return ;
}
sz[t]++;
if (k < key[t]) Insert(lch[t], k);
else Insert(rch[t], k);
Maintain(t, k >= key[t]);
}
void DeleteSmaller(int &t , Type k) {
if (0 == t) return ;
if ( key[t] < k ) {
t = rch[t];
DeleteSmaller(t , key);
} else {
DeleteSmaller(lch[t] , k);
sz[t] = 1 + sz[lch[t]] + sz[rch[t]];
}
}
Type Delete(int &t, Type k) {
sz[t]--;
if ((key[t] == k) || (k < key[t] && 0 == lch[t]) || (k > key[t] && 0 == rch[t])) {
Type tmp = key[t];
if (0 == lch[t] || 0 == rch[t]) {
t = lch[t] + rch[t];
} else {
key[t] = Delete(lch[t], key[t] + 1);
}
return tmp;
} else {
if (k < key[t]) {
return Delete(lch[t], k);
} else {
return Delete(rch[t], k);
}
}
}
private:
int root;
};
SBT<int> sbt[maxn<<2];
int n, q;
int a[maxn];
void Build(int l, int r, int rt)
{
sbt[rt].Clear();
for (int i = l; i <= r; ++i) {
sbt[rt].InsertR(a[i]);
}
if (l == r) return ;
int mid = (l + r) >> 1;
Build(l, mid, rt << 1);
Build(mid + 1, r, (rt << 1) | 1);
}
void Update(int l, int r, int rt, int p, int c)
{
sbt[rt].Delete(a[p]);
sbt[rt].InsertR(c);
if (l == r) return ;
int mid = (l + r) >> 1;
if (p <= mid) {
Update(l, mid, rt << 1, p, c);
} else {
Update(mid + 1, r, (rt << 1) | 1, p, c);
}
}
int Query(int l, int r, int rt, int L, int R, int X)
{
if (L <= l && R >= r) {
return sbt[rt].GetRank(X);
}
int mid = (l + r) >> 1;
if (R <= mid) {
return Query(l, mid, rt << 1, L, R, X);
}
if (L > mid) {
return Query(mid + 1, r, (rt << 1) | 1, L, R, X);
}
return Query(l, mid, rt << 1, L, mid, X) + Query(mid + 1, r, (rt << 1) | 1, mid + 1, R, X);
}
inline bool get(int &a)
{
char c;
while(((c=getchar())<'0'||c>'9')&&c!=EOF);
if(c==EOF)return 0;
for(a=0;c>='0'&&c<='9';c=getchar())a=a*10+c-'0';
return 1;
}
int main()
{
//freopen("racetime.in", "r", stdin);
//freopen("racetime.out1", "w", stdout);
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; ++i) {
//scanf("%d", &a[i]);
get(a[i]);
}
SBT<int>::ClearAll();
Build(1, n, 1);
char op[2];
int x, y, z;
while (q--) {
scanf("%s", op);
if (op[0] == 'C') {
//scanf("%d%d%d", &x, &y, &z);
get(x); get(y); get(z);
printf("%d\n", Query(1, n, 1, x, y, z));
} else {
//scanf("%d%d", &x, &y);
get(x); get(y);
Update(1, n, 1, x, y);
a[x] = y;
}
}
return 0;
}