线段树单点修改+区间最值。
其中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; }