这道题赤裸裸的线段树,不过就是输入有点难搞,加上错的方式很离谱就写上来了。(坑……)
一个数组,求指定区间内的最小值,输入:
query(3,7)代表查询第3至第7的最小值。
shift(2,4,5,7)代表把第2、4、5、7上的数依次向左移动一位。(每shift一次就更新线段树一次)#include<cstdio> #include<cstring> #define inf 0x3f3f3f3f int a[520000],min; int aa[100010]; int num[40]; int deal(char str[]){ memset(num,0,sizeof(num)); int start,end; int len = strlen(str); int pos = 0; for(int i=0;i<len;i++){ if(str[i]=='('||str[i]==','){ start = i+1; for(int j = i+1;;j++){ if(str[j]==','||str[j]==')'){ end = j-1; break; } } i = end; int mul = 1; for(int j=end;j>=start;j--){ num[pos] += (str[j]-'0')*mul; mul *= 10; } pos++; } } return pos; } void update(int pos,int price,int l,int r,int root) { int mid; if(l==r) { a[root]=price; return; } mid=(r+l)>>1; if(pos>mid) update(pos,price,mid+1,r,root<<1|1); else update(pos,price,l,mid,root<<1); if(a[root<<1|1]<a[root<<1])a[root]=a[root<<1|1]; else a[root]=a[root<<1]; return; } int query(int from,int to,int l,int r,int root) { int mid,ss; if(from<=l&&to>=r) return a[root]; mid=(l+r)>>1; if(mid>=from) { ss=query(from,to,l,mid,root<<1); if(min>ss) min=ss; } if(mid<to) { ss=query(from,to,mid+1,r,root<<1|1); if(min>ss) min=ss; } return min; } int main() { int t,m,n,k,i,j,f,ans; char order[40]; scanf("%d %d",&n,&m); for(i=0;i<520000;i++) a[i]=inf; for(i=1; i<=n; i++) { scanf("%d",&aa[i]); update(i,aa[i],1,n,1); } for(i=0; i<m; i++) { ans=inf; min=inf; scanf("%s",order); if(order[0]=='q') { int nncnt=deal(order); k=num[0]; t=num[1]; ans=query(k,t,1,n,1); printf("%d\n",ans); } if(order[0]=='s') { int ncnt=deal(order); int li=aa[num[0]]; for(j=0;j<ncnt-1;j++) { k=num[j]; t=aa[num[j+1]]; aa[k]=t; update(k,t,1,n,1); } k=num[j]; t=li; aa[k]=li; update(k,t,1,n,1); } } }