经过我不断地调试(抄代码) 终于过了这个题目=-=
首先由主席树为什么不能维护动态第K大呢
因为静态主席树所有[1, i]的区间在询问前就已经确定了
如果修改了一个位置的值 那么后面所有的区间都要修改 时间复杂度就变成了
是无法接受的
考虑用更灵活的数据结构而不是数组来维护修改
既然是前缀和当然就选择树状数组(线段树可能也可以)啦
原来我们每个点是维护的[1, i]序列的信息 用树状数组维护的化那么每个点倒他后面
个点进行一次
查询的时候也和静态主席树一样 不过用的是树状数组所包含的区间进行查询
那么就做到了
的复杂度 就ojbk了
模板。具体实现见代码。
#include<bits/stdc++.h>
#include<tr1/unordered_map>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
using namespace std;
tr1::unordered_map<int, int> id;
const int maxn = 2e4 + 10;
int T, n, q, root[maxn], rel[maxn], a[maxn], tmp[maxn], num;
int Sum2[maxn], Sum1[maxn];
struct Query
{
int opt, x, y, z, id;
}Q[maxn];
struct Fenwick_Tree_Cover_Chairman_Tree
{
#define ls(x) (T[x].l)
#define rs(x) (T[x].r)
#define mid ((l + r) >> 1)
int cnt;
struct node
{
int l, r, sum;
}T[maxn * 400];
int lowbit(int x)
{
return x & (-x);
}
void build(int &x, int l, int r)
{
x = ++ cnt;
if(l != r)
{
build(ls(x), l, mid);
build(rs(x), mid + 1, r);
}
}
void update(int &x, int pre, int l, int r, int p, int val)
{
T[x = ++ cnt] = T[pre];
T[x].sum += val;
if(l != r)
{
if(p <= mid)
update(ls(x), ls(pre), l, mid, p, val);
else
update(rs(x), rs(pre), mid + 1, r, p, val);
}
}
void add(int x, int y, int z)
{
for(register int i = x; i <= n; i += lowbit(i))
update(root[i], root[i], 1, num, y, z);
}
int query(int l, int r, int p)
{
if(l == r) return l;
int res = 0;
For(i, 1, Sum2[0])
res += T[ls(Sum2[i])].sum;
For(i, 1, Sum1[0])
res -= T[ls(Sum1[i])].sum;
if(res >= p)
{
For(i, 1, Sum2[0])
Sum2[i] = ls(Sum2[i]);
For(i, 1, Sum1[0])
Sum1[i] = ls(Sum1[i]);
return query(l, mid, p);
}
else
{
For(i, 1, Sum2[0])
Sum2[i] = rs(Sum2[i]);
For(i, 1, Sum1[0])
Sum1[i] = rs(Sum1[i]);
return query(mid + 1, r, p - res);
}
}
}Tree;
int main()
{
#ifndef ONLINE_JUDGE
freopen("1901.in", "r", stdin);
freopen("1901.out", "w", stdout);
#endif
char c;
scanf("%d%d", &n, &q);
For(i, 1, n)
scanf("%d", &a[i]), tmp[++ num] = a[i];
For(i, 1, q)
{
cin >> c;
if(c == 'C')
Q[i].opt = 0, scanf("%d%d", &Q[i].x, &Q[i].z), tmp[++ num] = Q[i].z;
else
Q[i].opt = 1, scanf("%d%d%d", &Q[i].x, &Q[i].y, &Q[i].z);
}
sort(tmp + 1, tmp + num + 1);
num = unique(tmp + 1, tmp + num + 1) - tmp - 1;
Tree.build(root[0], 1, num);
//update:这里应该写到For(i, 1, n)的 数据有点水啊...代码错的都过了..
//For(i, 1, num)
// root[i] = root[0];
For(i, 1, n)
a[i] = lower_bound(tmp + 1, tmp + num + 1, a[i]) - tmp, Tree.add(i, a[i], 1);
For(i, 1, q)
{
if(Q[i].opt)
{
Sum1[0] = Sum2[0] = 0;
for(register int j = Q[i].y; j; j -= Tree.lowbit(j))
Sum2[++ Sum2[0]] = root[j];
for(register int j = Q[i].x - 1; j; j -= Tree.lowbit(j))
Sum1[++ Sum1[0]] = root[j];
printf("%d\n", tmp[Tree.query(1, num, Q[i].z)]);
}
else
{
Tree.add(Q[i].x, a[Q[i].x], -1);
a[Q[i].x] = lower_bound(tmp + 1, tmp + num + 1, Q[i].z) - tmp;
Tree.add(Q[i].x, a[Q[i].x], 1);
}
}
return 0;
}