RMQ with Shifts
题意:
n个数两种操作,1、给出一组位置,使各位置的数循环移动,2、求给定区间的最小值。
分析:
单点更新,区间最值
#include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <string> #include <cctype> #include <complex> #include <cassert> #include <utility> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; typedef pair<int,int> PII; typedef long long ll; #define lson l,m,rt<<1 #define pi acos(-1.0) #define rson m+1,r,rt<<1|1 #define All 1,N,1 #define read freopen("in.txt", "r", stdin) const ll INFll = 0x3f3f3f3f3f3f3f3fLL; const int INF= 0x7ffffff; const int mod = 1000000007; int minv[100010*4],n,q,a[100010]; char s[35]; void pushup(int rt){ minv[rt]=min(minv[rt<<1],minv[rt<<1|1]); } void build(int l,int r,int rt){ if(l==r){ minv[rt]=a[l]; return; } int m=(l+r)>>1; build(lson); build(rson); pushup(rt); } void update(int p,int v,int l,int r,int rt){ if(l==r){ minv[rt]=v; return; } int m=(l+r)>>1; if(p<=m)update(p,v,lson); else update(p,v,rson); pushup(rt); } int query(int L,int R,int l,int r,int rt){ if(L<=l&&R>=r) return minv[rt]; int m=(l+r)>>1; int num=INF; if(L<=m)num=min(num,query(L,R,lson)); if(R>m) num=min(num,query(L,R,rson)); pushup(rt); return num; } int main() { int numb[15],id; scanf("%d%d",&n,&q); for(int i=1;i<=n;++i) scanf("%d",&a[i]); build(1,n,1); while(q--){ scanf("%s",s); int tmp=0; id=0; for(int i=6;s[i]!='\0';++i){ if(s[i]-'0'>=0&&s[i]-'0'<=9) tmp=tmp*10+s[i]-'0'; else if(s[i]==','||s[i]==')') { numb[id++]=tmp; tmp=0; } } if(s[0]=='q') printf("%d\n",query(numb[0],numb[1],1,n,1)); else{ int tmp=a[numb[0]]; for(int i=0;i<id-1;++i){ update(numb[i],a[numb[i+1]],1,n,1); a[numb[i]]=a[numb[i+1]]; } update(numb[id-1],tmp,1,n,1); a[numb[id-1]]=tmp; } } return 0; }