Description
Input
Output
Sample Input
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)
Sample Output
1 4 6
给你一个数组A是可变的,支持shift(i1,i2,...,ik),表示把元素A[i1],A[i2],....,A[ik],循环左移一位。query(L,R);是询问区间[L,R]的最小值。
算法思想:
比较简单的线段树点更新问题,把循环的更改的值依次单点更新即可。
#include <iostream> #include <cstdio> #include <cctype> #include <cstring> using namespace std; const int N = 100005; struct node{ int l,r,minn; }tree[N<<2]; int val[N],tmp[50],sum; void pushUp(int id){ tree[id].minn = min(tree[id<<1].minn,tree[id<<1|1].minn); } void build(int id,int l,int r){ tree[id].l = l; tree[id].r = r; if(tree[id].l == tree[id].r){ tree[id].minn = val[l]; return ; } int mid = (tree[id].l + tree[id].r)>>1; build(id<<1,l,mid); build(id<<1|1,mid+1,r); pushUp(id); } void update(int id,int x,int val){ if(tree[id].l == tree[id].r){ tree[id].minn = val; return ; } int mid = (tree[id].l+tree[id].r)>>1; if(x <= mid) update(id<<1,x,val); else update(id<<1|1,x,val); pushUp(id); } int query(int m,int l,int r){ if(tree[m].l == l && tree[m].r == r) return tree[m].minn; int mid = (tree[m].l+tree[m].r)>>1; if(r <= mid) return query(m<<1,l,r); if(l > mid) return query((m<<1)+1,l,r); return min(query(m<<1,l,mid), query((m<<1)+1,mid+1,r)); } void solve(){ char str[50]; int i,j,t; scanf("%s",str); int len = strlen(str); if(str[0] == 's'){ for(j = 0,i = 0; i < len; ++i){ if(!isdigit(str[i])) continue; int t = 0; while(isdigit(str[i])){ t = t*10+(str[i]-'0'); ++i; } tmp[j++] = t; } sum = j; t = val[tmp[0]]; for(i = 0; i < sum-1; ++i){ val[tmp[i]] = val[tmp[i+1]]; update(1,tmp[i],val[tmp[i]]); } val[tmp[i]] = t; update(1,tmp[i],val[tmp[i]]); }else{ for(j = 0,i = 0; i < len; ++i){ if(!isdigit(str[i])) continue; t = 0; while(isdigit(str[i])){ t = t*10+(str[i]-'0'); ++i; } tmp[j++] = t; } printf("%d\n",query(1,tmp[0],tmp[1])); } } int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ for(int i = 1; i <= n; ++i) scanf("%d",&val[i]); build(1,1,n); while(m--) solve(); } return 0; }