RMQ with Shifts
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each query (L, R) (L<=R), we report the minimum value among A[L], A[L+1], …, A[R]. Note that the indices start from 1, i.e. the left-most element is A[1].In this problem, the array A is no longer static: we need to support another operation shift(i1, i2, i3, …, ik) (i1<i2<...<ik, k>1): we do a left “circular shift” of A[i1], A[i2], …, A[ik].For example, if A={6, 2, 4, 8, 5, 1, 4}, then shift(2, 4, 5, 7) yields {6, 8, 4, 5, 4, 1, 2}. After that, shift(1,2) yields {8, 6, 4, 5, 4, 1, 2}.
-
输入
- There will be only one test case, beginning with two integers n, q (1<=n<=100,000, 1<=q<=120,000), the number of integers in array A, and the number of operations. The next line contains n positive integers not greater than 100,000, the initial elements in array A. Each of the next q lines contains an operation. Each operation is formatted as a string having no more than 30 characters, with no space characters inside. All operations are guaranteed to be valid. Warning: The dataset is large, better to use faster I/O methods. 输出
- For each query, print the minimum value (rather than index) in the requested range. 样例输入
-
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)
样例输出
-
1 4 6
来源
思路:
与基本的线段树差不多,只要理解他的移位就行了。如1,4,6. 1,4,6->4,1,6->4,6,1.这为数组下标,按下标将数组值交换就行了。
AC代码:
#include<iostream> #include<algorithm> #include<cstring> #include<string> #include<cstdio> using namespace std; #define T 300005 #define inf 0x3f3f3f3f int n,m,a[T],b[T]; struct node { int L,R; int min; }tree[T<<2]; void PushUp(int root) { tree[root].min = min(tree[root<<1].min,tree[root<<1|1].min); } void Build(int root,int L,int R) { tree[root].L = L,tree[root].R = R; tree[root].min = inf; if(L==R){ tree[root].min = a[L]; return; } int mid = (L+R)>>1; Build(root<<1,L,mid); Build(root<<1|1,mid+1,R); PushUp(root); } int qurey(int root,int L,int R) { if(tree[root].L==L&&tree[root].R==R){ return tree[root].min; } if(R<=tree[root<<1].R){ return qurey(root<<1,L,R); } else if(L>=tree[root<<1|1].L){ return qurey(root<<1|1,L,R); } else{ int mid = (tree[root].L+tree[root].R)>>1; int a = qurey(root<<1,L,mid); int b = qurey(root<<1|1,mid+1,R); return min(a,b); } } void UpDate(int root,int pos,int val) { if(tree[root].L == tree[root].R){ tree[root].min = val; return; } if(pos<=tree[root<<1].R){ UpDate(root<<1,pos,val); } else { UpDate(root<<1|1,pos,val); } PushUp(root); } int main() { /*freopen("input.txt","r",stdin);*/ int i,j,k,c; char str[6]; scanf("%d%d",&n,&m); for(i=1;i<=n;++i) scanf("%d",&a[i]); scanf("\n"); Build(1,1,n); while(m--) { c=0; scanf("%c%c%c%c%c%c",&str[0],&str[1],&str[2],&str[3],&str[4],&str[5]); if(str[0]=='q') { scanf("%d,%d)\n",&j,&k); printf("%d\n",qurey(1,j,k)); } else { while(scanf("%d,",&b[c++])==1); scanf(")\n"); for(i=1;i<c-1;++i){ a[b[i]]^=a[b[i-1]]; a[b[i-1]] = a[b[i]]^a[b[i-1]]; a[b[i]] = a[b[i-1]]^a[b[i]]; UpDate(1,b[i],a[b[i]]),UpDate(1,b[i-1],a[b[i-1]]); } } } return 0; }