卡我空间....
这道题应该是主席树入门题...无修改 , 离散化都不用...出题人业界良心啊
一开始的空白树我 build 出来结果就多了整整 2n 个 Node , 然后就 MLE 了...
( 双倍经验 , 另一道见上图 )
----------------------------------------------------------------------------------------------
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define rep( i , n ) for( int i = 0 ; i < n ; ++i )
#define clr( x , c ) memset( x , c , sizeof( x ) )
#define M( l , r ) ( ( ( l ) + ( r ) ) >> 1 )
using namespace std;
const int maxn = 500000 + 5;
struct Node {
Node *l , *r;
int s;
Node() : s( 0 ) {
l = r = this;
}
inline void update() {
s = l -> s + r -> s;
}
} pool[ 10700000 ] , *pt = pool , *root[ maxn ];
int v;
Node* modify( Node* t , int l , int r ) {
Node* h = pt++;
if( l == r )
h -> s = t -> s + 1;
else {
int m = M( l , r );
if( v <= m ) {
h -> l = modify( t -> l , l , m );
h -> r = t -> r;
} else {
h -> l = t -> l;
h -> r = modify( t -> r , m + 1 , r );
}
h -> update();
}
return h;
}
int query( Node* L , Node* R , int l , int r ) {
if( l == r ) return l;
int m = M( l , r );
if( R -> l -> s - L -> l -> s > v )
return query( L -> l , R -> l , l , m );
else if( R -> r -> s - L -> r -> s > v )
return query( L -> r , R -> r , m + 1 , r );
return 0;
}
int main(){
freopen( "test.in" , "r" , stdin );
root[ 0 ] = pt++;
int n , m;
cin >> n >> m;
rep( i , n ) {
scanf( "%d" , &v );
root[ i + 1 ] = modify( root[ i ] , 1 , n );
}
while( m-- ) {
int l , r;
scanf( "%d%d" , &l , &r );
v = ( r - l + 1 ) >> 1;
printf( "%d\n" , query( root[ l - 1 ] , root[ r ] , 1 , n ) );
}
return 0;
}
----------------------------------------------------------------------------------------------
3524: [Poi2014]Couriers
Time Limit: 20 Sec
Memory Limit: 128 MB
Submit: 782
Solved: 245
[
Submit][
Status][
Discuss]
Description
给一个长度为n的序列a。1≤a[i]≤n。
m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。
Input
第一行两个数n,m。
第二行n个数,a[i]。
接下来m行,每行两个数l,r,表示询问[l,r]这个区间。
Output
Sample Input
7 5
1 1 3 2 3 4 3
1 3
1 4
3 7
1 7
6 6
Sample Output
1
0
3
0
4
HINT
Source