线段树:n个数a[n],m个操作;
query(a,b):求a到b区间的最小值;
shift(……):shift里的数代表数组a的下标,把给定的下标的数向左移一位;
如:
7 5 6 2 4 8 5 1 4
shift(2,4,5,7)对应的数(2 8 5 4)
则数组变为:6 8 4 5 4 1 2;
#include <stdio.h> #include <string.h> #include <math.h> #include <string> #define INF 999999999 int min[100005*4],Ad[100005]; int cont; int Min(int a,int b) { if(a<b) return a; else return b; } void build(int l,int r,int rt) { if(l==r) { min[rt]=Ad[l]; return; } int mid=(l+r)/2; build(l,mid,rt*2); build(mid+1,r,rt*2+1); min[rt]=Min(min[rt*2],min[rt*2+1]); } int query(int l,int r,int L,int R,int rt) { if(l<=L && r>=R) return min[rt]; int mid=(L+R)/2; int ans=INF; if(l<=mid) ans=Min(ans,query(l,r,L,mid,rt*2)); if(r>mid) ans=Min(ans,query(l,r,mid+1,R,rt*2+1)); return ans; } void update(int l,int r,int rt,int u,int v) { if(l==r) { min[rt]=v; return; } int mid=(l+r)/2; if(u<=mid) update(l,mid,rt*2,u,v); else update(mid+1,r,rt*2+1,u,v); min[rt]=Min(min[rt*2],min[rt*2+1]); } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) scanf("%d",&Ad[i]); build(1,n,1); while(m--) { char ch[50]; scanf("%s",ch); if(ch[0]=='q') { int a,b; sscanf(ch+6,"%d,%d",&a,&b); printf("%d\n",query(a,b,1,n,1)); } else { int a[100]; int k=0; for(int i=6;ch[i]!='\n';) { int x=0; int j=i; while(ch[j]!=',' && ch[j]!=')') { x=x*10+ch[j]-'0'; j++; } a[++k]=x; if(ch[j]==')') break; else i=j+1; } int p=query(a[1],a[1],1,n,1);//找出下标为a[1]的数 p for(int i=1;i<k;i++) { int temp=query(a[i+1],a[i+1],1,n,1);//找出下标为a[i+1] 的数 temp update(1,n,1,a[i],temp);//更新下标 a[i] 的数为 下标a[i+1]的数 } update(1,n,1,a[k],p);//更新最后一位 } } } return 0; }