「TJOI / HEOI2016」排序
给定一个
1
1
~的排列,进行
m
m
次以下操作:
将区间
[l,r]
[
l
,
r
]
内的数降序排列
1 l r:
1
l
r
:
将区间
[l,r]
[
l
,
r
]
内的数升序排列
最后,给定一个位置,求出该位置的数。
n,m≤105 n , m ≤ 10 5
我们知道,对一个 01 01 串进行上述操作非常容易,用线段树就可以在 logn l o g n 的时间内完成一次操作。
我们考虑一下可不可以将这个问题转换为对 01 01 串的操作。
我们取一个数 val v a l ,设大于等于 val v a l 的值为 1 1 ,小于的值为 0 0 。这样我们操作后,如果询问的位置为,说明答案大于等于 val v a l ,否则说明答案小于 val v a l ,而一次操作是 O(mlogn) O ( m l o g n ) 的。
所以我们只需要二分一下 val v a l 即可在 O(mlog2n) O ( m l o g 2 n ) 内解决该题。
code:
#include <bits/stdc++.h>
using namespace std;
const int N = 100000;
int n, m, pos, a[N];
struct tModify {
int type, l, r;
} mdf[N];
struct tData {
int sum_0, sum_1;
tData() { sum_0 = sum_1 = 0; }
tData( int _sum_0, int _sum_1 ) { sum_0 = _sum_0; sum_1 = _sum_1; }
tData operator + ( const tData &rhs ) const {
return ( tData ) { sum_0 + rhs.sum_0, sum_1 + rhs.sum_1 };
}
} now;
struct segment_tree {
int sum[2][N<<2], opt[N<<2];
#define lson (o<<1)
#define rson (o<<1|1)
inline void pushup( int o, int l, int r ) {
sum[0][o] = sum[0][lson] + sum[0][rson];
sum[1][o] = sum[1][lson] + sum[1][rson];
assert( sum[0][o] + sum[1][o] == r - l + 1 );
}
#define pushup( o ) pushup( o, l, r )
inline void pushdown( int o, int l, int r )
{
if( opt[o] == -1 ) return;
int mid = l + r >> 1, tp = opt[o];
sum[tp][lson] = mid - l + 1;
sum[tp][rson] = r - mid;
sum[tp^1][lson] = sum[tp^1][rson] = 0;
opt[lson] = opt[rson] = tp;
opt[o] = -1;
}
inline void build( int o, int l, int r, int val )
{
opt[o] = -1;
if( l == r ) {
sum[a[l]>=val][o] = 1, sum[a[l]<val][o] = 0; return;
// if( a[l] >= val ) --> 1, else --> 0
}
int mid = l + r >> 1;
build( lson, l, mid, val );
build( rson,mid+1,r, val );
pushup( o );
}
inline tData query( int o, int l, int r, int ql, int qr )
{
if( ql <= l && r <= qr ) return ( tData ) { sum[0][o], sum[1][o] };
pushdown( o, l, r ); int mid = l + r >> 1; tData ret;
if( ql <= mid ) ret = ret + query( lson, l, mid, ql, qr );
if( mid+1<=qr ) ret = ret + query( rson,mid+1,r, ql, qr );
pushup( o );
return ret;
}
inline void modify_up( int o, int l, int r, int ql, int qr )
{
pushdown( o, l, r );
int mid = l + r >> 1, len = r - l + 1;
if( ql <= l && r <= qr )
{
if( now.sum_0 >= len ) {
sum[0][o] = len, sum[1][o] = 0, opt[o] = 0, now.sum_0 -= len; return;
}
if( !now.sum_0 ) {
sum[1][o] = len, sum[0][o] = 0, opt[o] = 1, now.sum_1 -= len; return;
}
modify_up( lson, l, mid, ql, qr );
modify_up( rson,mid+1,r, ql, qr );
pushup( o ); return;
}
if( ql <= mid ) modify_up( lson, l, mid, ql, qr );
if( mid+1<=qr ) modify_up( rson,mid+1,r, ql, qr );
pushup( o );
}
inline void modify_down( int o, int l, int r, int ql, int qr )
{
pushdown( o, l, r );
int mid = l + r >> 1, len = r - l + 1;
if( ql <= l && r <= qr )
{
if( now.sum_1 >= len ) {
sum[1][o] = len, sum[0][o] = 0, opt[o] = 1, now.sum_1 -= len; return;
}
if( !now.sum_1 ) {
sum[0][o] = len, sum[1][o] = 0, opt[o] = 0, now.sum_0 -= len; return;
}
modify_down( lson, l, mid, ql, qr );
modify_down( rson,mid+1,r, ql, qr );
pushup( o ); return;
}
if( ql <= mid ) modify_down( lson, l, mid, ql, qr );
if( mid+1<=qr ) modify_down( rson,mid+1,r, ql, qr );
pushup( o );
}
inline void print( int o, int l, int r )
{
if( l == r ) {
printf( "%d ", sum[1][o] == 1 ); return;
}
int mid = l + r >> 1; pushdown( o, l, r );
print( lson, l, mid );
print( rson,mid+1,r );
pushup( o );
}
#undef lson
#undef rson
} seg;
tData tmp; int ans;
inline bool check( int val )
{
seg.build( 1, 1, n, val );
// seg.print( 1, 1, n ); printf( "\n" );
for( int i = 1; i <= m; i ++ )
{
now = seg.query( 1, 1, n, mdf[i].l, mdf[i].r );
if( mdf[i].type )
seg.modify_down( 1, 1, n, mdf[i].l, mdf[i].r );
else seg.modify_up( 1, 1, n, mdf[i].l, mdf[i].r );
}
// seg.print( 1, 1, n ); printf( "\nval:%d\n",val );
now = seg.query( 1, 1, n, pos, pos );
// printf( "val:%d, tmp:%d %d\n", val, now.sum_0, now.sum_1 );
return now.sum_1 == 1;
}
void solve( int l, int r )
{
if( l > r ) return;
int mid = l + r >> 1;
bool b = check( mid );
if( b ) {
ans = mid; solve( mid+1, r );
}
else solve( l, mid-1 );
}
int main()
{
// freopen( "sort4.in", "r", stdin );
scanf( "%d%d", &n, &m );
for( int i = 1; i <= n; i ++ )
scanf( "%d", &a[i] );
for( int i = 1; i <= m; i ++ )
scanf( "%d%d%d", &mdf[i].type, &mdf[i].l, &mdf[i].r );
scanf( "%d", &pos );
solve( 1, n );
printf( "%d\n", ans );
return 0;
}