大家都很强, 可与之共勉。
q l, r, k
查询[l, r] 第k小。
m pos, x;
把pos位置的改为x。
每次询问就是对O(logn) 棵树加加减减后求第k 大。修改也会同时修改O(logn) 棵树,所以总的复杂度是:O((m+n)log^2 n)。
#include "cstdio"
#include "cctype"
#include "cstdlib"
#include "cstring"
#define lowbit(x) (x & (-x))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define rep(i, m, n) for(register int i = (m); i <= (n); ++i)
template <class T>
inline bool readIn(T &x) {
T flag = 1; char ch;
while(!(isdigit(ch = (char) getchar())) && ch != EOF) if( ch == '-' ) flag = -1;
if(ch == EOF) return false;
for(x = ch - 48; isdigit(ch = (char) getchar()); x = (x << 1) + (x << 3) + ch - 48);
x *= flag;
return true;
}
template <class T>
inline void write(T x) {
if (x > 9)
write(x / 10);
putchar(x % 10 + 48);
}
template <class T>
inline bool writeIn(T x) {
if (x < 0) {
putchar('-');
x = -x;
}
write(x);
return true;
}
class io {
public:
io() {
freopen("intkth.in", "r", stdin);
freopen("intkth.out", "w", stdout);
}
~io() {
fclose(stdin);
fclose(stdout);
}
} M;
const int MAXN = 100005;
struct Node {
int cnt;
Node *ls, *rs;
Node(int cnt = 0, Node *ls = NULL, Node *rs = NULL) : cnt(cnt), ls(ls), rs(rs) { }
} pool[MAXN * 200], *tail = pool, *roots[MAXN], *null;
int ca, cb, n, m, l, r, k, pos, val, a[MAXN];
Node *va[10001], *vb[10001];
inline void init() {
null = ++tail;
null -> ls = null;
null -> rs = null;
null -> cnt = 0;
}
inline Node *newnode() {
Node *nd = ++tail;
nd->ls = null;
nd->rs = null;
nd->cnt = 0;
return nd;
}
void modify( int lf, int rg, int pos, int delta ) {
for(register int i = 0; i < ca; va[i]->cnt += delta, ++i);
if( lf ^ rg ) {
int mid = (lf + rg) >> 1;
if( pos <= mid ) {
for( int t = 0; t < ca; t++ ) {
if( va[t]->ls == null )
va[t]->ls = newnode();
va[t] = va[t]->ls;
}
modify( lf, mid, pos, delta );
} else {
for(register int i = 0; i < ca; ++i) {
if( va[i] -> rs == null )
va[i] -> rs = newnode();
va[i] = va[i] -> rs;
}
modify( mid + 1, rg, pos, delta );
}
}
}
int query_seg( int lf, int rg, int k ) {
if( lf == rg ) return lf;
int mid = (lf + rg) >> 1;
int lz = 0;
for(register int i = 0; i < ca; ++i) lz += va[i] -> ls -> cnt;
for(register int i = 0; i < cb; ++i) lz -= vb[i] -> ls -> cnt;
if( k <= lz ) {
for(register int i = 0; i < ca; ++i) va[i] = va[i]->ls;
for(register int i = 0; i < cb; ++i) vb[i] = vb[i]->ls;
return query_seg( lf, mid, k );
} else {
for(register int i = 0; i < ca; ++i) va[i] = va[i] -> rs;
for(register int i = 0; i < cb; ++i) vb[i] = vb[i] -> rs;
k -= lz;
return query_seg( mid + 1, rg, k );
}
}
inline void modify( int u, int x, int delta ) {
ca = 0;
for( register int i = u; i <= n; i += lowbit(i) )
va[ca++] = roots[i];
modify( 1, n, x, delta );
}
inline void modify( int u, int x ) {
modify( u, a[u], -1 );
modify( u, x, +1 );
a[u] = x;
}
inline int query( int l, int r, int k ) {
ca = cb = 0;
for( register int i = r; i; i -= lowbit(i) )
va[ca++] = roots[i];
for( register int i = l - 1; i; i -= lowbit(i) )
vb[cb++] = roots[i];
return query_seg(1, n, k);
}
int main() {
readIn(n);readIn(m);
rep(i, 1, n) readIn(a[i]);
init();
rep(i, 1, n) roots[i] = newnode();
rep(i, 1, n) modify( i, a[i], +1 );
while( m-- ) {
static char s;
while((s = (char) getchar()) == ' ' || s == '\n');
if( s == 'q' ) {
readIn(l);readIn(r);readIn(k);
writeIn(query(l, r, k)); putchar(10);
} else {
readIn(pos);readIn(val);
modify( pos, val );
}
}
return 0;
}