RT,本人代码:
#include <bits/stdc++.h>
// #pragma GCC optimize(2)
#define ll long long
#define For( i , j , k ) for( int i = ( j ) ; i <= ( k ) ; ++ i )
using namespace std;
template < typename T >
inline T read( T &num ){
num = 0 ; T f = 1 ; char c = ' ';
while( c < '0' || c > '9' ) if( ( c = getchar() ) == '-' ) f = -1;
while( c >= '0' && c <= '9' ) num = ( num << 1 ) + ( num << 3 ) + ( c ^ 48 ) , c = getchar();
num *= f; return num;
}
//-------------------------Fastio end-------------------------//
const int maxn = 5e5 + 5;
const int INF = ( 1ll << 29 );
/*
我的思路,有问题欢迎dalao指出:
对于第二种操作,我们可以维护一个用线段树维护一个lst[ i ]的最大值和a[ i ]的最大值和最小值
lst[ i ]: 当前a[ i ]这个数之前出现的下标
可以发现当区间[l,r]为值域上连续的一段时,当且仅当:
( max - min + 1 ) == ( r - l + 1 ) && max{ lst[ i ] } < l }
考虑修改操作,我们再维护一个lst[ i ]
nxt[ i ]: 当前a[ i ]这个数下次再出现的下标
每次我们修改一个数x为y时,只会修改5个数的nxt/lst
分别是nxt[ x ] , lst[ x ] , x , x前面最靠近它的y ,x的后面最靠近它的y
前两种可以O(1)解决,对于后两种我们给每个数a[ i ]维护一个set,内存它的下标,二分即可
别忘了给a[ i ]离散化
*/
int n , m;
int a[ maxn << 1 ];
struct Node{
int st; bool nd;
bool operator < ( const Node &y ) const{ return st < y.st; }
bool operator < ( const int &y ) const{ return st < y; }
bool operator == ( const int &y ) const{ return st == y; }
bool operator == ( const Node &y ) const{ return st == y.st; }
}b[ maxn << 1 ];
int cnt_b;
int nxt[ maxn << 1 ] , lst[ maxn << 1 ];
inline int bfind( int x ){ return lower_bound( b + 1 , b + cnt_b + 1 , x ) - b; }
set< int > buc[ maxn << 1 ];
struct Ask{ int opt , x , y; }ask[ maxn ];
struct Segment_Tree{//线段树
#define ls ( p << 1 )
#define rs ( p << 1 | 1 )
struct Tree{
int pmaxs , maxs , mins;
Tree operator + ( const Tree &y ) const{
Tree ans;
ans = Tree{ max( pmaxs , y.pmaxs ) , max( maxs , y.maxs ) , min( mins , y.mins ) };
return ans;
}
}trees[ maxn << 2 ];
inline void push_up( int p ){ trees[ p ] = trees[ ls ] + trees[ rs ]; }
inline void build( int l , int r , int p ){
trees[ p ] = Tree{ -INF , -INF , INF };
if( l == r ){
trees[ p ] = Tree{ lst[ l ] , a[ l ] , a[ l ] };
return ;
}
int mid = l + r >> 1;
build( l , mid , ls ) , build( mid + 1 , r , rs );
push_up( p );
}
inline void update( int l , int r , int x , int kp , int k , int p ){
if( l == r ){
if( k == INF ) trees[ p ].pmaxs = kp;
else trees[ p ] = Tree{ kp , k , k };
return ;
}
int mid = l + r >> 1;
if( x <= mid ) update( l , mid , x , kp , k , ls );
else update( mid + 1 , r , x , kp , k , rs );
push_up( p );
}
inline Tree query( int l , int r , int x , int y , int p ){
if( x <= l && r <= y ) return trees[ p ];
int mid = l + r >> 1;
if( y <= mid ) return query( l , mid , x , y , ls );
else if( mid < x ) return query( mid + 1 , r , x , y , rs );
return query( l , mid , x , mid , ls ) + query( mid + 1 , r , mid + 1 , y , rs );
}
}seg;
inline bool check( int l , int r ){
Segment_Tree :: Tree ans = seg.query( 1 , n , l , r , 1 );
if( ans.maxs - ans.mins + 1 == r - l + 1 && ans.pmaxs < l ) return true;
return false;
}
inline void upd( int x , int y ){
nxt[ lst[ x ] ] = nxt[ x ];
lst[ nxt[ x ] ] = lst[ x ];//要修改
seg.update( 1 , n , nxt[ x ] , lst[ x ] , INF , 1 );
buc[ a[ x ] ].erase( x );
a[ x ] = y;
set< int > :: iterator it = buc[ y ].upper_bound( x );
it --; lst[ x ] = *it;//要修改
seg.update( 1 , n , x , lst[ x ] , y , 1 );
it ++; if( it != buc[ y ].end() ) nxt[ x ] = *it;
nxt[ lst[ x ] ] = lst[ nxt[ x ] ] = x;//要修改
seg.update( 1 , n , nxt[ x ] , x , INF , 1 );
buc[ y ].insert( x );
}
int main(){
// freopen( "data.in" , "r" , stdin );
// freopen( "data.out" , "w" , stdout );
read( n ) , read( m );
For( i , 1 , n ) b[ ++ cnt_b ] = Node{ read( a[ i ] ) , 0 };//0为属于a
For( i , 1 , m ){
read( ask[ i ].opt ) , read( ask[ i ].x ) , read( ask[ i ].y );
if( ask[ i ].opt == 1 ) b[ ++ cnt_b ] = Node{ ask[ i ].y , 1 };//1为属于询问操作
}
sort( b + 1 , b + cnt_b + 1 );
cnt_b = unique( b + 1 , b + cnt_b + 1 ) - b - 1;//b数组离散化
For( i , 1 , n ) a[ i ] = bfind( a[ i ] );
For( i , 1 , m ) if( ask[ i ].opt == 1 ) ask[ i ].y = bfind( ask[ i ].y );
int cnt_a = n;
For( i , 1 , cnt_b ){
buc[ i ].insert( 0 );
if( !b[ i ].nd ) a[ ++ cnt_a ] = i;//把b数组中属于a的在a中复制一遍,就不用特判边界了
}
For( i , 1 , cnt_a ){
lst[ i ] = *buc[ a[ i ] ].rbegin();
nxt[ lst[ i ] ] = i;
buc[ a[ i ] ].insert( i );
}
seg.build( 1 , n , 1 );
For( i , 1 , m ){
if( ask[ i ].opt == 1 ) upd( ask[ i ].x , ask[ i ].y );
else puts( check( ask[ i ].x , ask[ i ].y ) ? "damushen" : "yuanxing" );
}
return 0;
}
新人刚学OI,求助