题目分析:今天不适合做题!不对。。。是昨天。。
这题可以用线段树来做,只要每次R x的时候维护位移,然后F就维护是否旋转,然后需要用到L,R时就转化为L,R实际应该在的位置,线段树搞搞好了。需要注意的是,如果是询问C且整串为一种颜色应该输出1。
写这题的时候真是逗的不行了。。CS i j询问的是一个段,然后我以为如果j+1==i则就和C一样了。。。我说为什么不考虑这个就能过。。考虑了就wa。。T U T
代码如下:
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; #define REP( i , a , b ) for ( int i = ( a ) ; i < ( b ) ; ++ i ) #define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i ) #define REV( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i ) #define CLR( a , x ) memset ( a , x , sizeof a ) #define CPY( a , x ) memcpy ( a , x , sizeof a ) #define ls ( o << 1 ) #define rs ( o << 1 | 1 ) #define lson ls , l , m #define rson rs , m + 1 , r #define mid ( ( l + r ) >> 1 ) #define root 1 , 1 , n #define rt o , l , r const int MAXN = 500005 ; int lnum[MAXN << 2] , rnum[MAXN << 2] ; int set[MAXN << 2] , sum[MAXN << 2] ; int n , q ; bool rev ; int move ; char op[5] ; void pushup ( int o ) { sum[o] = sum[ls] + sum[rs] ; lnum[o] = lnum[ls] ; rnum[o] = rnum[rs] ; if ( rnum[ls] == lnum[rs] ) -- sum[o] ; } void pushdown ( int o ) { if ( set[o] ) { sum[ls] = sum[rs] = 1 ; lnum[ls] = rnum[ls] = set[o] ; lnum[rs] = rnum[rs] = set[o] ; set[ls] = set[rs] = set[o] ; set[o] = 0 ; } } void update ( int L , int R , int v , int o , int l , int r ) { if ( L <= l && r <= R ) { sum[o] = 1 ; set[o] = v ; lnum[o] = rnum[o] = v ; return ; } int m = mid ; pushdown ( o ) ; if ( L <= m ) update ( L , R , v , lson ) ; if ( m < R ) update ( L , R , v , rson ) ; pushup ( o ) ; } int query ( int L , int R , int o , int l , int r ) { if ( L <= l && r <= R ) return sum[o] ; int m = mid ; pushdown ( o ) ; if ( R <= m ) return query ( L , R , lson ) ; if ( m < L ) return query ( L , R , rson ) ; return query ( L , R , lson ) + query ( L , R , rson ) - ( rnum[ls] == lnum[rs] ) ; } int query_color ( int pos , int o , int l , int r ) { while ( l != r ) { int m = mid ; pushdown ( o ) ; if ( pos <= m ) { r = m ; o = ls ; } else { l = m + 1 ; o = rs ; } } return lnum[o] ; } void build ( int o , int l , int r ) { set[o] = 0 ; if ( l == r ) { scanf ( "%d" , &lnum[o] ) ; rnum[o] = lnum[o] ; sum[o] = 1 ; return ; } int m = mid ; build ( lson ) ; build ( rson ) ; pushup ( o ) ; } void maintain ( int& L , int& R ) { if ( rev ) { L = ( 2 * n - move - L + 1 ) % n + 1 ; R = ( 2 * n - move - R + 1 ) % n + 1 ; swap ( L , R ) ; } else { L = ( L - move + n - 1 ) % n + 1 ; R = ( R - move + n - 1 ) % n + 1 ; } } void scanf ( int&x , char c = 0 ) { while ( ( c = getchar () ) < '0' || c > '9' ) ; x = c - '0' ; while ( ( c = getchar () ) >= '0' && c <= '9' ) x = x * 10 + c - '0' ; } void solve () { int L , R , v , ans ; move = rev = 0 ; scanf ( "%d%*d" , &n ) ; build ( root ) ; scanf ( "%d" , &q ) ; while ( q -- ) { scanf ( "%s" , op ) ; if ( op[1] == 'S' ) { scanf ( L ) , scanf ( R ) ; maintain ( L , R ) ; //printf ( "%d %d\n" , L , R ) ; if ( L <= R ) ans = query ( L , R , root ) ; else { ans = query ( 1 , R , root ) + query ( L , n , root ) ; if ( rnum[1] == lnum[1] ) -- ans ; } printf ( "%d\n" , ans ) ; } else if ( op[0] == 'R' ) { scanf ( v ) ; if ( rev ) move = ( move - v + n ) % n ; else move = ( move + v ) % n ; } else if ( op[0] == 'F' ) rev ^= 1 ; else if ( op[0] == 'S' ) { scanf ( L ) , scanf ( R ) ; maintain ( L , R ) ; //printf ("swap : %d %d\n" , L , R ) ; int Lv = query_color ( L , root ) ; int Rv = query_color ( R , root ) ; update ( L , L , Rv , root ) ; update ( R , R , Lv , root ) ; } else if ( op[0] == 'P' ) { scanf ( L ) , scanf ( R ) , scanf ( v ) ; maintain ( L , R ) ; if ( L <= R ) update ( L , R , v , root ) ; else update ( 1 , R , v , root ) , update ( L , n , v , root ) ; } else printf ( "%d\n" , sum[1] - ( lnum[1] == rnum[1] && sum[1] > 1 ) ) ; } } int main () { //freopen ( "necklace.in" , "r" , stdin ) ; //freopen ( "necklace.out" , "w" , stdout ) ; solve () ; return 0 ; }