线段树单点修改+区间最值。
其中shift的操作,只需要挨个改值就行了。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#define ll long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN 500005
#define LEN 111111<<2
using namespace std;
struct Segment_tree
{
int _min[LEN];
int ql,qr,sz,sp,sv;
private:
void pushup(int o)
{
_min[o]=min(_min[o<<1],_min[o<<1|1]);
}
void myupdate(int o,int L,int R)
{
if(L==R) _min[o]=sv;
else
{
int M=(L+R)>>1;
if(sp<=M) myupdate(o<<1,L,M);
else myupdate(o<<1|1,M+1,R);
pushup(o);
}
}
void mybuild(int o,int L,int R)
{
if(L==R) scanf("%d",&_min[o]);
else
{
int M=(L+R)>>1;
mybuild(o<<1,L,M);
mybuild(o<<1|1,M+1,R);
pushup(o);
}
}
int myquery(int o,int L,int R)
{
if(ql<=L&&R<=qr) return _min[o];
int M=(L+R)>>1;
int res=INF;
if(ql<=M) res=min(res,myquery(o<<1,L,M));
if(M<qr) res=min(res,myquery(o<<1|1,M+1,R));
return res;
}
public:
void clear(int n)
{
sz=n;
int len=n<<2;
for(int i=0; i<len; ++i)
_min[i]=INF;
// memset(_min,0x7f,sizeof(_min));
}
void build()
{
mybuild(1,1,sz);
}
void update(int p,int v)
{
sp=p;
sv=v;
myupdate(1,1,sz);
}
int query(int L,int R)
{
ql=L;
qr=R;
return myquery(1,1,sz);
}
};
Segment_tree tree;
int arr[200];
char str[35];
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int t;
tree.clear(n);
tree.build();
for(int i=1; i<=m; ++i)
{
scanf("%s",str);
if(str[0]=='q')
{
int x,y;
sscanf(str,"query(%d,%d)",&x,&y);
printf("%d\n",tree.query(x,y));
}
else if(str[0]=='s')
{
int val=0,k=0;
for(int i=6; str[i]; ++i)
{
if(isdigit(str[i])) val=val*10+str[i]-'0';
else
{
arr[k++]=val;
val=0;
}
}
int temp=tree.query(arr[0],arr[0]);
for(int i=1; i<k; ++i)
{
int v=tree.query(arr[i],arr[i]);
tree.update(arr[i-1],v);
}
tree.update(arr[k-1],temp);
}
}
}
return 0;
}