ZOJ 2112 Dynamic Rankings(Treap套在线段树上...)

搞得最凄惨的一个题了。。。

各种不AC,MLE,RE,TLE,WA什么都有。。

要注意节点要计重

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<cstdlib>
using namespace std;

#define inf 0x3f3f3f3f
#define eps 1e-8
#define LL long long 
#define ULL unsigned long long
#define MP make_pair
#define ls i << 1
#define rs ls | 1
#define mxn 50040

struct node {
	node *ch[2];
	int v, r, s, cnt;
	node() {}
	node( int v ): v( v ) {
		r = rand();
		ch[0] = ch[1] = NULL;
		s = 1;
		cnt = 1;
	}
	int cmp( int x ) {
		if( x == v )
			return -1;
		return x < v ? 0: 1;
	}
	void mt() {
		s = cnt;
		if( ch[0] )
			s += ch[0] -> s;
		if( ch[1] )
			s += ch[1] -> s;
	}
}pool[900003];
int sz = 0;
node *creat() {
	node *p = &pool[sz++];
	p -> s = 1;
	p -> ch[0] = p -> ch[1] = NULL;
	p -> r = rand();
	p -> cnt = 1;
	return p;
}
struct treap {
	node *root;
	treap() {
		root = NULL;
	}
	void rt( node *&p, int d ) {
		node *k = p -> ch[d^1];
		p -> ch[d^1] = k -> ch[d];
		k -> ch[d] = p;
		p -> mt();
		k -> mt();
		p = k;
	}
	void insert( node *&p, int x ) {
		if( p == NULL ) {
			p = creat();
			p -> v = x;
			return;
		}
		int d = p -> cmp( x );
		if( d == -1 ) {
			p -> cnt++;
			p -> s ++;
			return;
		}
		insert( p -> ch[d], x );
		if( p -> ch[d] -> r > p -> r )
			rt( p, d ^ 1 );
		p -> mt();
	}
	void remove( node *&p, int x ) {
		int d = p -> cmp( x );
		if( d == -1 ) {
			if( p -> cnt > 1 ) {
				p -> cnt--, p -> s--;
			}
			else {
				if( p -> ch[0] && p -> ch[1] ) {
					int d2 = p -> ch[0] -> r > p -> ch[1] -> r? 1: 0;
					rt( p, d2 );
					remove( p -> ch[d2], x );
				}
				else
					if( p -> ch[0] == NULL )
						p = p -> ch[1];
					else
						p = p -> ch[0];
			}
		}
		else
			remove( p -> ch[d], x );
		if( p )
			p -> mt();
	}
	bool find( node *p, int x ) {
		if( p == NULL )
			return 0;
		int d = p -> cmp( x );
		if( d == -1 )
			return 1;
		return find( p -> ch[d], x );
	}
	int kth( node *p, int k ) {
		if( p == NULL || k <= 0 || k > p -> s )
			return 0;
		int s = p -> ch[0] == NULL ? 0: p -> ch[0] -> s;
		if( k == s + 1 )
			return p -> v;
		if( k <= s ) 
			return kth( p -> ch[0], k );
		return kth( p -> ch[1], k - s - 1 );
	}
	int rk( node *p, int x ) {
		if( p == NULL )
			return 0;
		int R;
		if( p -> ch[0] == NULL )
			R = 0;
		else
			R = p -> ch[0] -> s;
		if( x == p -> v ) {
			return R + p -> cnt;
		}
		if( x < p -> v ) {
			return rk( p -> ch[0], x );
		}
		return rk( p -> ch[1], x ) + R + p -> cnt;
	}
};
int ll[mxn<<2], rr[mxn<<2], a[mxn];
treap T[mxn<<2];
void build( int l, int r, int i ) {
	ll[i] = l, rr[i] = r;
	T[i].root = NULL;
	if( l == r ) {
		T[i].insert( T[i].root, a[l] );
		return;
	}
	int m = ( l + r ) >> 1;
	build( l, m, ls );
	build( m + 1, r, rs );
	for( int j = l; j <= r; ++j )
		T[i].insert( T[i].root, a[j] );
}
void update( int k, int x, int y, int i ) {
	T[i].remove( T[i].root, x );
	T[i].insert( T[i].root, y );
	if( ll[i] == rr[i] ) {
		return;
	}
	int m = ( ll[i] + rr[i] ) >> 1;
	if( k <= m ) {
		update( k, x, y, ls );
	}
	else {
		update( k, x, y, rs );
	}
}
int find( int l, int r, int k, int i ) {
	if( ll[i] == l && rr[i] == r ) {
		return T[i].rk( T[i].root, k );
	}
	int m = ( ll[i] + rr[i] ) >> 1;
	if( r <= m ) 
		return find( l, r, k, ls );
	if( l > m )
		return find( l, r, k, rs );
	return find( l, m, k, ls ) + find( m + 1, r, k, rs );
}
void init() {
	memset( T, 0, sizeof( T ) );
	memset( pool, 0, sizeof( pool ) );
	sz = 0;
}
int main() {
//	freopen( "test.txt", "r", stdin );
	int cas;
	scanf( "%d", &cas );
	while( cas-- ) {
		init();
		int n, m;
		scanf( "%d%d", &n, &m );
		for( int i = 1; i <= n; ++i )
			scanf( "%d", &a[i] );
		build( 1, n, 1 );
		char type[5];
		for( int i = 1; i <= m; ++i ) {
			scanf( "%s", type );
			if( type[0] == 'C' ) {
				int k, t;
				scanf( "%d%d", &k, &t );
				update( k, a[k], t, 1 );
				a[k] = t;
				continue;
			}
			int l, r, k;
			scanf( "%d%d%d", &l, &r, &k );
			int head, tail;
			head = 0, tail = inf;
			while( head < tail ) {
				int mid = ( head + tail ) >> 1;
				if( find( l, r, mid, 1 ) < k ) {
					head = mid + 1;
				}
				else 
					tail = mid;
			}
			printf( "%d\n", head );
		}
	}
	return 0;
}


你可能感兴趣的:(ZOJ 2112 Dynamic Rankings(Treap套在线段树上...))