题意:线段修改时要把选出来的数字全部右移一位修改掉。
题解:单点修改线段树模板题,把挑出来的逐个单点修改就好。
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int N = 400000;
const int INF = 0x3f3f3f3f;
int s[N], l[N], r[N], a[N], b[N], b1[N];
int l1, r1, n, m, flag, u, x;
void build(int k, int left, int right) {
if (left == right) {
l[k] = left;
r[k] = left;
s[k] = a[left];
return;
}
int mid = (left + right) / 2;
build(k * 2, left, mid);
build(k * 2 + 1, mid + 1, right);
s[k] = s[k * 2] < s[k * 2 + 1] ? s[k * 2] : s[k * 2 + 1];
l[k] = left;
r[k] = right;
}
int query(int k, int left, int right) {
if (l1 <= l[k] && r1 >= r[k])
return s[k];
int mid = (l[k] + r[k]) / 2;
int ans = INF;
if (l1 <= mid)
ans = min(ans, query(k * 2, left, mid));
if (r1 > mid)
ans = min(ans, query(k * 2 + 1, mid + 1, right));
return ans;
}
void change(int k) {
if (l[k] == u && r[k] == u) {
s[k] = x;
return;
}
int mid = (l[k] + r[k]) / 2;
if (u <= mid)
change(k * 2);
else
change(k * 2 + 1);
s[k] = s[k * 2] < s[k * 2 + 1] ? s[k * 2] : s[k * 2 + 1];
}
int main() {
while (scanf("%d%d", &n, &m) == 2) {
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, 1, n);
char str[100];
while (m--) {
scanf("%s", str);
int len = strlen(str), k = 0;
if (str[0] == 'q')
flag = 1;
else
flag = 2;
for (int i = 1; i < len; i++) {
if (str[i] <= '9' && str[i] >= '0') {
int temp = 0;
while (str[i] <= '9' && str[i] >= '0')
temp = temp * 10 + str[i++] - '0';
b[k++] = temp;
}
}
if (flag == 1) {
l1 = b[0];
r1 = b[1];
printf("%d\n", query(1, 1, n));
}
else {
for (int i = 0; i < k; i++)
b1[i] = a[b[i]];
for (int i = 0; i < k - 1; i++)
a[b[i]] = b1[i + 1];
a[b[k - 1]] = b1[0];
for (int i = 0; i < k - 1; i++) {
u = b[i];
x = b1[i + 1];
change(1);
}
u = b[k - 1];
x = b1[0];
change(1);
}
}
}
return 0;
}