In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each query (L, R) (L<=R), 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 shift(i1, i2, i3, …, ik) (i1<i2<...<ik,k>1): ( i 1 < i 2 < . . . < i k , k > 1 ) : we do a left “circular shift” of A[i1], A[i2], …, A[ik].
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}.
在传统的RMQ(Range Minimum Query)问题中,我们有一个静态数组A.然后对于每个查询(L,R)(L <= R),我们报告A [L],A [L + 1 ],…,A [R]。 请注意,索引从1开始,即最左边的元素是A [1]。
在这个问题中,数组A不再是静态的:我们需要支持另一个操作移位 (i1,i2,i3,...,ik)(i1<i2<...<ik,k>1) ( i 1 , i 2 , i 3 , . . . , i k ) ( i 1 < i 2 < . . . < i k , k > 1 ) :我们做一个左移 A [i1],A [i2],…,A [ik]的“循环移位”。
例如,如果A = {6,2,4,8,5,1,4},则移位(2,4,5,7)产生{6,8,4,5,4,1,2}。 之后,移位(1,2)产生{8,6,4,5,4,1,2}。
Input
There will be only one test case, beginning with two integers n, q (1<=n<=100,000, 1<=q<=120,000), the number of integers in array A, and the number of operations. The next line contains n positive integers not greater than 100,000, the initial elements in array A. Each of the next q lines contains an operation. Each operation is formatted as a string having no more than 30 characters, with no space characters inside. All operations are guaranteed to be valid. Warning: The dataset is large, better to use faster I/O methods.
将只有一个测试用例,以两个整数n,q(1 <= n <= 100,000,1 <= q <= 120,000),数组A中的整数数量以及操作次数开始。 下一行包含n个不大于100,000的正整数,即数组A中的初始元素。下一个q行中的每一行都包含一个操作。 每个操作都被格式化为不超过30个字符的字符串,里面没有空格字符。 所有操作都保证有效。 警告:数据集很大,最好使用更快的I / O方法。
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
思路:单点修改,区间查询最小值,线段树裸题。要注意的是注意处理输入字符串,修改值时保存存最后一个值,最后修改‘
#include
#include
#include
#include
using namespace std;
typedef long long LL;
const int MAXN = 2e5 + 10;
char str[1010];
int dp[MAXN << 2], a[MAXN << 1];
int ans;
inline void pushup(int root) {
dp[root] = min(dp[root << 1], dp[root << 1 | 1]);
}
inline void build(int root, int L, int R) {
if(L == R) {
scanf("%d", &a[L]);
dp[root] = a[L];
return ;
}
int mid = (L + R) >> 1;
build(root << 1, L, mid);
build(root << 1 | 1, mid + 1, R);
pushup(root);
}
inline void updata(int root, int L, int R, int x, int y) {
if(L == R) {
dp[root] = a[y];
a[x] = a[y];
return ;
}
int mid = (L + R) >> 1;
if(x <= mid) updata(root << 1, L, mid, x, y);
else updata(root << 1 | 1, mid + 1, R, x, y);
pushup(root);
}
inline void updata_cnt(int root, int L, int R, int x, int y) {
if(L == R) {
dp[root] = y;
a[x] = y;
return ;
}
int mid = (L + R) >> 1;
if(x <= mid) updata_cnt(root << 1, L, mid, x, y);
else updata_cnt(root << 1 | 1, mid + 1, R, x, y);
pushup(root);
}
inline void query(int root, int L, int R, int l, int r) {
if(L >= l && R <= r) {
ans = min(ans, dp[root]);
return;
}
int mid = (L + R) >> 1;
if(mid >= l) query(root << 1, L, mid, l, r);
if(r > mid) query(root << 1 | 1, mid + 1, R, l, r);
}
int main() {
int n, m;
scanf("%d %d", &n, &m);
build(1, 1, n);
while(m--) {
scanf("%s", str);
int len = strlen(str);
int b[110], p = 0, res = 0;
for(int i = 6; i < len; ++i) { //注意处理字符串,数位比较多
if(str[i] >= '0' && str[i] <= '9') {
res = res * 10 + str[i] - '0';
}
else if(str[i] != ')') {
b[p++] = res;
res = 0;
}
else break;
}
b[p++] = res;
if(str[0] == 'q') {
ans = 0x3f3f3f3f;
query(1, 1, n, b[0], b[1]);
printf("%d\n", ans);
}
else {
int cnt = a[b[0]];
for(int i = 0; i < p - 1; i++) {
updata(1, 1, n, b[i], b[i + 1]);
}
updata_cnt(1, 1, n, b[p - 1], cnt); //修改最后一个值
}
}
return 0;
}