由于命令长度最大才30,shift操作包含位置的数量不超过12,可以视为常数。
把每一个shift操作当成N个单点修改即可。
对命令字符串解析,使用:
for(int j=0;j<len;j++){
if(isdigit(s[j])){
sscanf(&s[j],"%d",&pos[p++]);
}
while(isdigit(s[j])){
j++;
}
}
比较方便。
代码:
#include <iostream> #include <cstdio> #include <cstring> using namespace std; #include <algorithm> #define maxn 100005 int a[maxn<<2]; int n[maxn]; #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define INF 10000000 void pushup(int rt){ int lc=rt<<1,rc=rt<<1|1; a[rt]=min(a[lc],a[rc]); } void build(int rt,int l,int r){ if(l==r){ a[rt]=n[l]; return ; } int mid=(l+r)>>1; build(lson); build(rson); pushup(rt); } void update(int rt,int l,int r,int pos,int num){ if(l==r){ a[rt]=num; return ; } int mid=(l+r)>>1; if(mid>=pos) update(lson,pos,num); else update(rson,pos,num); pushup(rt); } int Query(int rt,int l,int r,int L,int R){ if(l>=L&&r<=R){ return a[rt]; } int mid=(l+r)>>1; int res=INF; if(mid>=L) res=min(res,Query(lson,L,R)); if(mid<R) res=min(res,Query(rson,L,R)); return res; } int N,Q; int main(){ scanf("%d%d",&N,&Q); for(int i=1;i<=N;i++){ scanf("%d",&n[i]); } build(1,1,N); for(int i=1;i<=Q;i++){ char s[40]; scanf("%s",s); if(s[0]=='q'){ int pos[2]; int p=0; int len=strlen(s); for(int j=0;j<len;j++){ if(isdigit(s[j])){ sscanf(&s[j],"%d",&pos[p++]); } while(isdigit(s[j])){ j++; } } printf("%d\n",Query(1,1,N,pos[0],pos[1])); } else{ int pos[30]; int p=0; int len=strlen(s); for(int j=0;j<len;j++){ if(isdigit(s[j])){ sscanf(&s[j],"%d",&pos[p++]); } while(isdigit(s[j])){ j++; } } for(int k=0;k<p;k++){ int next=(k+1)%p; update(1,1,N,pos[k],n[pos[next]]); } int tmp=n[pos[0]]; for(int j=0;j<p-1;j++){ n[pos[j]]=n[pos[j+1]]; } n[pos[p-1]]=tmp; } } return 0; } /* 7 5 6 2 4 8 5 1 4 query(3,7); shift(2,4,5,7); query(1,4); shift(1,2); query(2,2); */