树状数组套主席树
好像没有什么特别的地方,就是要注意卡空间。
先处理出初始序列的主席树
O(N∗log(N+M))
然后用树状数组记录修改
O(M∗logN∗log(N+M))
时间复杂度/空间复杂度:
O((N+M∗logN)∗log(N+M))
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <string>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <utility>
#include <iostream>
#include <algorithm>
#define lowbit(x) ((x)&(-x))
#define REP(__i,__start,__end) for(int __i = (__start); __i <= (__end); __i++)
#define REPt(__i,__start) for(int __i = (__start); __i > 0; __i -= lowbit(__i))
template<class Num>void read(Num &x)
{
char c; int flag = 1;
while((c = getchar()) < '0' || c > '9')
if(c == '-') flag *= -1;
x = c - '0';
while((c = getchar()) >= '0' && c <= '9')
x = (x<<3) + (x<<1) + (c-'0');
x *= flag;
return;
}
template<class Num>void write(Num x)
{
if(x < 0) putchar('-'), x = -x;
static char s[20];int sl = 0;
while(x) s[sl++] = x%10 + '0',x /= 10;
if(!sl) {putchar('0');return;}
while(sl) putchar(s[--sl]);
}
const int maxn = 5e4+5,maxm = 1e4+5, logN = 40, size = 2e6;
int n, m;
struct TreeNode
{
int l, r, cnt;
}Emp, S[size];
int tot, root[maxn<<1], a[maxn];
struct vetor
{
#define begin() (__arr + 1)
#define end() (__arr + __len + 1)
int *__arr, __len;
void set(int size)
{
__len = 0, __arr = (int*)malloc(sizeof(int)*size);
}
void push_back(int x)
{
__arr[++__len] = x;
}
int size()
{
return __len;
}
void unique()
{
std::sort(begin(),end());
__len = std::unique(begin(),end()) - begin();
}
int find(int x)
{
return std::lower_bound(begin(), end(), x)-begin()+1;
}
int get(int x)
{
return __arr[x];
}
int count()
{
int ret = 0;
#define Lcnt(x) S[S[x].l].cnt
REP(i, 1, __len) ret += Lcnt(__arr[i]);
#undef Lcnt
return ret;
}
void erase()
{
__len = 0;
}
int gain(int x)
{
erase(), push_back(root[n + x]);
REPt(i, x) push_back(root[i]);
}
void move(int tp)
{
if(tp) REP(i, 1, __len) __arr[i] = S[__arr[i]].r;
else REP(i, 1, __len) __arr[i] = S[__arr[i]].l;
}
#undef begin
#undef end
}arr, Tl, Tr;
int NewNode()
{
S[++tot] = Emp;
return tot;
}
int TreeAdd(int now,int ll,int rr,int k,int val)
{
int ret = NewNode();
if(ll == rr)
S[ret].cnt = S[now].cnt + val;
else
{
int mid = (ll + rr) >> 1;
if(k <= mid)
{
S[ret].l = TreeAdd(S[now].l, ll, mid, k, val);
S[ret].r = S[now].r, S[ret].cnt = S[S[ret].l].cnt + S[S[ret].r].cnt;
}
else
{
S[ret].r = TreeAdd(S[now].r, mid + 1, rr, k, val);
S[ret].l = S[now].l, S[ret].cnt = S[S[ret].l].cnt + S[S[ret].r].cnt;
}
}
return ret;
}
void ArrayAdd(int x,int ts,int val)
{
while(x <= n)
{
root[x] = TreeAdd(root[x], 1, arr.size(), ts, val);
x += lowbit(x);
}
}
int Build(int ll,int rr)
{
int ret = NewNode();
if(ll != rr)
{
int mid = (ll + rr) >> 1;
S[ret].l = Build(ll, mid);
S[ret].r = Build(mid + 1, rr);
}
return ret;
}
void PreWork()
{
root[0] = Build(1, arr.size());
REP(i, 1, n) root[i] = root[0];
REP(i, 1, n) root[n+i] = TreeAdd(root[n+i-1], 1, arr.size(), arr.find(a[i]), 1);
}
struct operator_import
{
int type, i, j, t;
void scan()
{
char c[3];
scanf("%s",c), type = (c[0] == 'C');
if(type)
read(i), read(t), arr.push_back(t);
else
read(i), read(j), read(t);
}
int query(int l,int r,int k)
{
int ll = 1, rr = arr.size();
Tl.gain(l-1), Tr.gain(r);
while(ll != rr)
{
int mid = (ll + rr)>>1, cnt = 0;
cnt += Tr.count(), cnt -= Tl.count();
if(k <= cnt)
Tl.move(0), Tr.move(0), rr = mid;
else
k -= cnt, Tl.move(1), Tr.move(1), ll = mid + 1;
}
return ll;
}
void solve()
{
if(type)
{
ArrayAdd(i, arr.find(a[i]), -1);
ArrayAdd(i, arr.find(t), 1), a[i] = t;
}
else
write(arr.get(query(i, j, t))),puts("");
}
}op[maxm];
int main()
{
int T;
#ifndef ONLINE_JUDGE
freopen("zoj2112.in","r",stdin);
freopen("zoj2112.out","w",stdout);
#endif
arr.set(maxn + maxm), Tl.set(logN), Tr.set(logN);
std::cin >> T;
while(T--)
{
tot = 0, arr.erase();
std::cin >> n >> m;
REP(i, 1, n) read(a[i]), arr.push_back(a[i]);
REP(i, 1, m) op[i].scan();
arr.unique(), PreWork();
REP(i, 1, m) op[i].solve();
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}