# [SMOJ2212]郁闷的小J

//2212.cpp
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

typedef pair <int, int> pii;

const int MAXN = 1e5 + 500;

int N, M;
int a[MAXN], pos[MAXN << 1];
char opt[MAXN << 1];
pii books[MAXN << 1];
vector <pii> queries;

int block_len, block_cnt;
int b[317][MAXN];

int block_id(int pos) { //查询所在块 id
return (pos - 1) / block_len + 1;
}

void block_update(int pos, int val) { //更新块
int id = block_id(pos);
--b[id][a[pos]]; //删除旧的
++b[id][val];
a[pos] = val; //维护新的
}

int block_query(int l, int r, int v) { //区间查询
int l_id = block_id(l), r_id = block_id(r); //端点所在块
int ans = 0;
if (l_id == r_id) {
for (int i = l; i <= r; i++) ans += a[i] == v; //在同一块内，直接暴力统计
return ans;
}
for (int i = l_id + 1; i < r_id; i++) ans += b[i][v]; //在它们之间的可以整块直接加

//两边的区间都分类讨论一下，如果恰好包含了整块也直接加，否则暴力统计
int ll = (l_id - 1) * block_len + 1, lr = l_id * block_len;
if (l == ll) ans += b[l_id][v];
else
for (int i = l; i <= lr; i++) ans += a[i] == v;

int rl = (r_id - 1) * block_len + 1, rr = r_id * block_len;
if (r == rr) ans += b[r_id][v];
else
for (int i = rl; i <= r; i++) ans += a[i] == v;
return ans;
}

int main(void) {
freopen("2212.in", "r", stdin);
freopen("2212.out", "w", stdout);
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; i++) {
int num; scanf("%d", &num);
books[i] = make_pair(num, i);
}
for (int i = 1; i <= M; i++) {
char tmp[2]; scanf("%s", tmp); opt[i] = tmp[0];
if (opt[i] == 'C') {
int A, P; scanf("%d%d", &A, &P);
books[N + i] = make_pair(P, N + i);
}
if (opt[i] == 'Q') {
int A, B, K; scanf("%d%d%d", &A, &B, &K);
queries.push_back(make_pair(A, B));
books[N + i] = make_pair(K, N + i);
}
}
sort(books + 1, books + N + M + 1); //这题的离散化比较麻烦，需要将所有数据统一先读入

int ranking = 0;
for (int i = 1; i <= N + M; i++)
pos[books[i].second] = (ranking += books[i].first != books[i - 1].first);
for (int i = 1; i <= N; i++) a[i] = pos[i]/*, printf("%d\n", a[i])*/;

block_len = sqrt(N); block_cnt = block_len + (bool)(N % block_len); //最后多出来的新开一块
for (int i = 1; i <= block_cnt; i++) //先 O(n) 算出初始时各块信息
for (int j = (i - 1) * block_len + 1; j <= i * block_len; j++)
++b[i][a[j]];

int p_upd = 0, p_qry = 0;
for (int i = 1; i <= M; i++) {
if (opt[i] == 'C') block_update(updates[p_upd++], pos[N + i]);
if (opt[i] == 'Q') printf("%d\n", block_query(queries[p_qry].first, queries[p_qry].second, pos[N + i])), ++p_qry;
}
return 0;
}

…………

#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

typedef pair <int, int> pii;

const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 100;
const int MAXM = 1e5 + 100;

struct Tnode {
Tnode *child[2];
int val, fix;
int siz;
Tnode (int v = 0) : val(v), fix(rand()), siz(1) { child[0] = child[1] = NULL; }
void update() { siz = (child[0] ? child[0] -> siz : 0) + (child[1] ? child[1] -> siz : 0) + 1; }
} nodes[MAXN << 1], *current;

struct Treap {
Tnode *root;
Treap () : root(NULL) {}

Tnode *get_node(int v) {
(*current) = Tnode(v);
return current ++;
}

void rotate(Tnode *&cur, int dir) {
Tnode *ch = cur -> child[dir ^ 1];
cur -> child[dir ^ 1] = ch -> child[dir];
ch -> child[dir] = cur;

cur -> update();
ch -> update();
cur = ch;
}

void insert_val(Tnode *&cur, int v) {
if (!cur) { cur = get_node(v); return ; }
int t = v > cur -> val;
insert_val(cur -> child[t], v);
if (cur -> child[t] -> fix < cur -> fix) rotate(cur, t ^ 1); else cur -> update();
}

void remove_val(Tnode *&cur, int v) {
if (!cur) return ;
if (cur -> val == v) {
if (!cur -> child[0] && !cur -> child[1]) { cur = NULL; return ; }
else if (cur -> child[0] && cur -> child[1]) {
int t = cur -> child[0] -> fix < cur -> child[1] -> fix;
rotate(cur, t);
remove_val(cur -> child[t], v);
} else if (cur -> child[0]) cur = cur -> child[0]; else cur = cur -> child[1];
} else remove_val(cur -> child[v > cur -> val], v);
cur -> update();
}

int query_section(Tnode *cur, int l, int r) {
if (!cur || l > r) return 0;
if (r < cur -> val) return query_section(cur -> child[0], l, r);
else if (l > cur -> val) return query_section(cur -> child[1], l, r);
else return query_section(cur -> child[0], l, cur -> val - 1) + 1 + query_section(cur -> child[1], cur -> val + 1, r);
}

int query_leq(Tnode *cur, int v) { //以 cur 为根的子树中，值小于等于 v 的结点数
if (!cur) return 0;
if (v <= cur -> val) return query_leq(cur -> child[0], v) + (v == cur -> val);
//小于当前结点，则只有左子树才有可能有答案。注意小于等于可以跟小于合并处理，缩短代码量。
else return (cur -> child[0] ? cur -> child[0] -> siz : 0) + 1 + query_leq(cur -> child[1], v); //大于当前结点，则左子树和当前结点肯定都小于 v
}
} treaps[MAXN << 1];

int N, M, pos[MAXN << 1], A[MAXN << 1];
char opt[MAXM << 1];
pii books[MAXN << 1];
vector <pii> queries;

int main(void) {
freopen("2212.in", "r", stdin);
freopen("2212.out", "w", stdout);
scanf("%d%d", &N, &M);
for (int i = 1; i <= N; i++) {
int num; scanf("%d", &num);
books[i] = make_pair(num, i);
}
for (int i = 1; i <= M; i++) {
char tmp[2]; scanf("%s", tmp); opt[i] = tmp[0];
if (opt[i] == 'C') {
int A, P; scanf("%d%d", &A, &P);
books[N + i] = make_pair(P, N + i);
}
if (opt[i] == 'Q') {
int A, B, K; scanf("%d%d%d", &A, &B, &K);
queries.push_back(make_pair(A, B));
books[N + i] = make_pair(K, N + i);
}
}
sort(books + 1, books + N + M + 1);
//  for (int i = 1; i <= N; i++) printf("(%d, %d) ", books[i].first, books[i].second);
int ranking = 0;
for (int i = 1; i <= N + M; i++)
pos[books[i].second] = (ranking += books[i].first != books[i - 1].first);
//  for (int i = 1; i <= N + M; i++) printf("%d ", pos[i]);
current = nodes;
for (int i = 1; i <= N; i++) A[i] = pos[i], treaps[pos[i]].insert_val(treaps[pos[i]].root, i);
int p_upd = 0, p_qry = 0;
for (int i = 1; i <= M; i++) {
if (opt[i] == 'C') {
treaps[pos[N + i]].insert_val(treaps[pos[N + i]].root, updates[p_upd]);
}
if (opt[i] == 'Q') printf("%d\n", treaps[pos[N + i]].query_leq(treaps[pos[N + i]].root, queries[p_qry].second) - treaps[pos[N + i]].query_leq(treaps[pos[N + i]].root, queries[p_qry].first - 1)/*query_section(treaps[pos[N + i]].root, queries[p_qry].first, queries[p_qry].second)*/), ++p_qry;
}
return 0;
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120