也是模板线段树.
只是需要对输入进行一些处理.
还有就是修改时候,不是普通的单点修改,要把shift里面的位置按顺序左移一位,第一个变成最后一个,第二个变成第一个.
用for来循环单点修改:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100005;
const int INF = 0x3f3f3f3f;
int s[N << 2] ,lc[N << 2] ,rc[N << 2];
int n,m,num[N];
void build(int u ,int l ,int r) {
lc[u] = l;
rc[u] = r;
if(l == r) {
s[u] = num[l];
return ;
}
int mid = (l + r) / 2;
build(u * 2 , l , mid);
build(u * 2 + 1 , mid + 1 ,r);
s[u] = min(s[u * 2] , s[u * 2 + 1]);
}
void shift(int u , int x , int v) {
if(lc[u] == x && rc[u] == x) {
s[u] = v;
return ;
}
int mid = (lc[u] + rc[u]) / 2;
if(x <= mid)
shift(u * 2 , x , v);
else
shift(u * 2 + 1 , x , v);
s[u] = min(s[u * 2] , s[u * 2 + 1]);
}
int query(int u , int l ,int r) {
int res = INF;
if(l <= lc[u] && r >= rc[u]) {
return s[u];
}
int mid = (lc[u] + rc[u]) / 2;
if(l <= mid)
res = min(res , query(u * 2 , l , r));
if(r > mid)
res = min(res , query(u * 2 + 1 , l , r));
return res;
}
int main() {
scanf("%d%d",&n,&m);
for(int i = 1; i <= n ; i++) {
scanf("%d",&num[i]);
}
char str[35];
build(1 , 1 , n);
while(m--) {
scanf("%s",str);
if(str[0] == 'q') {
int a[2] = {0};
int j = 0;
for (int i = 6 ; str[i] != ')' ;i++) {
if(str[i] == ',') {
j++;
continue;
}
a[j] = (a[j] * 10) + str[i] - '0';
}
printf("%d\n",query(1 , a[0] , a[1]));
}
if(str[0] == 's') {
int f[30] = {0};
int k[30];
int len = 0;
for (int i = 6 ; str[i] != ')' ; i++) {
if(str[i] == ',') {
len++;
continue;
}
f[len] = (f[len] * 10) + str[i] - '0';
}
int temp = num[f[0]];
for (int i = 0 ; i < len ;i++) {
shift(1 , f[i] , num[f[i + 1]]);
num[f[i]] = num[f[i + 1]];
}
shift(1,f[len] , temp);
num[f[len]] = temp;
}
}
}