Uva 12299 RMQ with Shifts (线段树 + 单点更新)
题意:
对于给定的序列 x[i]
给出一个操作 shift(a,b,c,d,e) 对应的是将 x[a]与x[b] x[b]与x[c] 这样相邻的两两交换
For example, if A={6, 2, 4, 8, 5, 1, 4}
then shift(2, 4, 5, 7) yields {6, 8, 4, 5, 4, 1, 2}.
After that,shift(1, 2) yields {8, 6, 4, 5, 4, 1, 2}.
分析:
实际上也是单点更新,考虑的时候考虑复杂了,
这里有一个关键点是 shift[0]最后移动到shift[cnt-1]的位置
其他就是基本的单点更新操作了。
--cnt; int t = x[shift[0]]; REP( i, 0, cnt ) { x[shift[i]] = x[shift[i+1]]; Update( shift[i], x[shift[i]], 1, n, 1 ); } x[shift[cnt]] = t; Update( shift[cnt], x[shift[cnt]], 1, n, 1 );
//#define BUG #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <vector> #include <list> #include <queue> #include <ctime> #include <iostream> #include <cmath> #include <set> #include <string> using namespace std; typedef long long LL; typedef unsigned long long ULL; #define INF 0x7fffffff #define MAX 0x3f3f3f3f #define CLR( a, b ) memset( a, b, sizeof(a) ) #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 FOD( i, a, b ) for( int i = (a); i >=(b); --i ) #define MID ( l + r ) >> 1 #define lson l, m, o << 1 #define rson m + 1, r, o << 1 | 1 #define ls o << 1 #define rs o << 1 | 1 #define MAXN 100010 int tree[MAXN << 2]; int x[MAXN]; int cnt; int shift[33]; char str[33]; void PushUp( int o ) { tree[o] = min( tree[ls], tree[rs] ); } void Build( int l, int r, int o ) { if( l == r ) { tree[o] = x[l]; return; } int m = MID; Build( lson ); Build( rson ); PushUp( o ); } void Update( int pos, int v, int l, int r, int o ) { if(l == r) { tree[o] = v; return; } int m = MID; if( pos <= m ) Update( pos, v, lson ); else Update( pos, v, rson ); PushUp( o ); } int Query( int L, int R, int l, int r, int o ) { if( L == l && r == R ) { return tree[o]; } int m = MID; if( R <= m ) return Query( L, R, lson); else if( L > m ) return Query( L, R, rson); else { return min( Query( L, m, lson ), Query( m + 1, R, rson ) ); } } int GetOP() { CLR( shift, 0 ); cnt = 0; scanf( "%s", str ); int i = 0; while( str[i] ) { int t = 0; int flag = 0; while( str[i] >= '0' && str[i] <= '9' ) { flag = 1; t = t*10 + str[i] - '0'; i++; } if( flag ) shift[ cnt++ ] = t; else i++; } /* puts(""); for(int i=0;i<cnt;i++) printf( "%d ", shift[i] ); puts(""); */ if(str[0] == 'q') return true; else return false; } void Orz() { #ifdef BUG freopen("in.txt","r",stdin); #endif int n, p; scanf( "%d %d", &n, &p ); FOR( i, 1, n ) scanf( "%d",&x[i] ); Build( 1, n, 1 ); while( p-- ) { if( GetOP() ) { printf( "%d\n", Query( shift[0], shift[1], 1, n, 1 ) ); } else { --cnt; int t = x[shift[0]]; REP( i, 0, cnt ) { x[shift[i]] = x[shift[i+1]]; Update( shift[i], x[shift[i]], 1, n, 1 ); } x[shift[cnt]] = t; Update( shift[cnt], x[shift[cnt]], 1, n, 1 ); } } } int main() { Orz(); return 0; }