RMQ with Shifts |
In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each query (L, R)(LR), we report the minimum value among A[L], A[L + 1], ..., A[R]. Note that the indices start from 1, i.e. the left-most element is A[1].
In this problem, the array A is no longer static: we need to support another operation
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.
Warning: The dataset is large, better to use faster I/O methods.
7 5 6 2 4 8 5 1 4 query(3,7) shift(2,4,5,7) query(1,4) shift(1,2) query(2,2)
1 4 6
The Seventh Hunan Collegiate Programming Contest
Problemsetter: Rujia Liu, Special Thanks: Yiming Li & Jane Alam Jan
运用线段树的查询区间最值和单点修改。
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <map> #include <string> #include <stack> #include <cctype> #include <vector> #include <queue> #include <set> using namespace std; //#define Online_Judge #define outstars cout << "***********************" << endl; #define clr(a,b) memset(a,b,sizeof(a)) #define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++) #define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++) #define REP(i , x , n) for(int i = (x) ; i > (n) ; i--) #define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--) const int MAXN = 100000 + 50; const int maxw = 100 + 20; const int MAXNNODE = 1000000 +10; const long long LLMAX = 0x7fffffffffffffffLL; const long long LLMIN = 0x8000000000000000LL; const int INF = 0x7fffffff; const int IMIN = 0x80000000; #define eps 1e-8 #define mod 1000000007 typedef long long LL; const double PI = acos(-1.0); typedef double D; typedef pair<int , int> pi; struct Node { int left; int right; int minx; }; int n , q ; Node node[4*MAXN];/*最多需要分配的空间*/ int number[MAXN]; //向上更新 void push_up(int pos) { node[pos].minx = min(node[pos<<1].minx , node[(pos<<1)+1].minx);/*向上更新当前点的信息*/ } /*建立空的二叉树,初始化每个营地人数为0*/ void buildTree(int left , int right , int pos) { node[pos].left = left; node[pos].right = right; if(left == right) { node[pos].minx = number[left]; return; } /*递归建立子树*/ int mid = (left+right)>>1; buildTree(left , mid , pos<<1); buildTree(mid+1 , right , (pos<<1)+1); push_up(pos); } /*单点更新*/ void update(int p , int d , int l , int r ,int pos) { if(l == r) { number[l] = d; node[pos].minx = d; return; } int m = (l + r) >> 1; if(p <= m)update(p , d , l , m , pos << 1); else update(p , d , m + 1 , r ,(pos << 1) + 1); push_up(pos); } int query(int ql,int qr,int l,int r,int s) { if(ql <= l&&r <= qr) return node[s].minx; int m = (l + r)>>1,ans=INF; if(ql <= m) ans = min(ans,query(ql , qr , l , m , s << 1)); if(qr > m) ans = min(ans,query(ql , qr , m + 1 , r , (s << 1) + 1)); return ans; } char s[35]; vector<int> V , A; int main() { //ios::sync_with_stdio(false); #ifdef Online_Judge freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif // Online_Judge while(scanf("%d%d", &n ,&q) == 2) { FORR(i , 1 , n)scanf("%d" , &number[i]); buildTree(1 , n , 1); while(q--) { scanf("%s" , s); int len = strlen(s); if(s[0] == 'q') { int a = 0; int b = 0; int i = 4; while(s[i] != ',') { if(isdigit(s[i])) { a = a * 10 + s[i] -'0'; } i++; } while(i < len) { if(isdigit(s[i])) { b = b * 10 + s[i] - '0'; } i++; } printf("%d\n" , query(a , b , 1 , n ,1)); } else { int i = 4; V.clear(); A.clear(); while(i < len) { int a = 0; while(s[i] != ','&&s[i] != ')') { if(isdigit(s[i])) { a = a * 10 + s[i] - '0'; } i++; } i++; V.push_back(a); A.push_back(number[a]); } int b = A[0]; A.erase(A.begin()); A.push_back(b); FOR(k , 0 , V.size())update(V[k] , A[k] , 1 , n , 1); } } } return 0; }