UVA - 12299
Description ![]()
|
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
Source
Root :: AOAPC I: Beginning Algorithm Contests -- Training Guide (Rujia Liu) :: Chapter 3. Data Structures :: Maintaining Interval Data :: Exercises: Beginner
题意:
对于序列A,有两种操作:
query(L,R) 询问[L, R]直接的最小值
shift(k1, k2, k3...) A[k1] A[k2] A[k3] ... 依次循环左移一位
因为shift移动元素很少,所以对于shift直接暴力移动,然后线段树维护最小值就行了
WA了好多次
后来发现移动的代码出了问题 ╮(╯▽╰)╭
#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>
using namespace std;
//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif
#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)
const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = (4.0*atan(1.0));
const int maxn = 100000 + 20;
const int maxo = maxn * 4;
LL minv[maxo];
LL A[maxn];
void build(int o, int L, int R) {
if(L == R) {
minv[o] = A[L];
return ;
}
int M = L + (R-L) / 2;
build(o*2, L, M);
build(o*2+1, M+1, R);
minv[o] = min(minv[o*2], minv[o*2+1]);
}
int qx, qv;
void update(int o, int L, int R) {
if(L == qx && qx == R) {
minv[o] = qv;
return ;
}
int M = L + (R-L) / 2;
if(qx <= M) update(o*2, L, M);
else update(o*2+1, M+1, R);
minv[o] = min(minv[o*2], minv[o*2+1]);
}
int ql, qr;
LL query(int o, int L, int R) {
if(ql <= L && R <= qr) {
return minv[o];
}
int M = L + (R-L) / 2;
LL res = INF;
if(ql <= M) res = min(res, query(o*2, L, M));
if(M < qr) res = min(res, query(o*2+1, M+1, R));
return res;
}
char str[100];
int move[40];
int getIntegers(char * s) {
int num = 0;
int len = strlen(str);
int p = 0;
while(p < len) {
int x = 0;
while(p < len && (str[p] < '0' || str[p] > '9')) p++;
while(p<len && str[p] >= '0' && str[p] <= '9') {
x = x * 10 + str[p] - '0';
p++;
}
if(x) move[num++] = x;
}
return num;
}
int main() {
int n, m;
while(scanf("%d%d", &n, &m) != EOF) {
for(int i=1; i<=n; i++) scanf("%lld", &A[i]);
build(1, 1, n);
while(m--) {
scanf("%s", str);
int num = getIntegers(str);
if(str[0] == 'q') {
ql = move[0], qr = move[1];
LL ans = query(1, 1, n);
P64I(ans);
} else {
for(int i=0; i<num; i++) {
qx = move[i];
qv = A[move[(i+1)%num]];
update(1, 1, n);
}
int t = A[move[0]];
for(int i=0; i<num-1; i++) {
A[move[i]] = A[move[i+1]];
}
A[move[num-1]] = t;
}
}
}
return 0;
}