题意:在传统的RMQ的基础上加上一个操作:shift(i1,i2,i3...ik),表示将这些元素,依次向左移动一位
思路:在原先线段树的基础上再加上:首先要先得到该位的数字,那么就是在[i,i]的区间找最小值,然后将该位置的值修改为后一位
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 100010;
const int INF = 0x3f3f3f3f;
int n,m,a[MAXN<<2];
int q[33],tmp[33];
char str[33];
void build(int l,int r,int c){
if (l == r){
scanf("%d",&a[c]);
return;
}
int mid = (l+r) >> 1;
build(l,mid,c<<1);
build(mid+1,r,c<<1|1);
a[c] = min(a[c<<1],a[c<<1|1]);
}
void update(int l,int r,int p,int d,int c){
if (l == r){
a[c] = d;
return;
}
int mid = (l+r) >> 1;
if (p <= mid)
update(l,mid,p,d,c<<1);
else update(mid+1,r,p,d,c<<1|1);
a[c] = min(a[c<<1],a[c<<1|1]);
}
int query(int l,int r,int ll,int rr,int c){
int mid = l + (r-l) / 2,ans = INF;
if (ll <= l && rr >= r)
return a[c];
if (ll <= mid)
ans = min(ans,query(l,mid,ll,rr,c<<1));
if (rr > mid)
ans = min(ans,query(mid+1,r,ll,rr,c<<1|1));
return ans;
}
void solve(){
int sp = 6;
int cnt = 0;
while (1){
int tot = 0;
while (str[sp] >= '0' && str[sp] <= '9')
tot = tot*10 + (str[sp++] - '0');
q[cnt++] = tot;
if (str[sp] == ',')
sp++;
else break;
}
if (str[0] == 's'){
for (int i = 0; i < cnt; i++)
tmp[i] = query(1,n,q[i],q[i],1);
for (int i = 0; i < cnt; i++)
update(1,n,q[i],tmp[(i+1)%cnt],1);
}
else printf("%d\n",query(1,n,q[0],q[1],1));
}
int main(){
scanf("%d%d",&n,&m);
build(1,n,1);
while (m--){
scanf("%s",str);
solve();
}
return 0;
}