RMQ with Shifts
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.
Input
There will be only one test case, beginning with two integers n, q ( 1



Warning: The dataset is large, better to use faster I/O methods.
Output
For each query, print the minimum value (rather than index) in the requested range.Sample Input
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)
Sample Output
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;
}
UVA的第150题!Mark一下,继续加油!