CSU-1110 RMQ with Shifts (单点更新+区间最小值 zkw线段树)

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, 85, 1, 4}, then shift(2, 4, 5, 7) yields {68, 4, 5, 4, 1, 2}. After that, shift(1,2) yields {8, 6, 4, 5, 4, 1, 2}.

Input

There will be only one test case, beginning with two integers nq (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.

Output

For each query, print the minimum value (rather than index) in the requested range.

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

看题目的开始可以知道,是一个求区间最小值的问题,可以用线段树来解决,看了后半段,感觉是单点更新问题,但看了数据范围时,有点蒙了,普通的操作会超时吧。。。卡了一段时间没敢写,然后,然后,竟然过了。。。唉,没经验啊。。。

题意就是给出一段序列,有两种操作,第一种是区间查询最小值,第二种是shift,就是按照给出的位置的数据循环左移一位。

代码如下:

#include<iostream>
#include<cstring>
#include<sstream>
#include<cstdio>

using namespace std;
const int N = 100000 + 5;
const int INF = (1<<30);
int T[N<<2],a[N],q[N],M,cnt;
char ch[N];
void Build(int n){
    int i;
    for(M=1;M<=n+1;M*=2);
    for(i=M+1;i<=M+n;i++) T[i]=a[cnt++];
    for(i=M-1;i;i--) T[i]=min(T[i<<1],T[i<<1|1]);
}

void Updata(int n,int V){
    for(T[n+=M]=V,n/=2;n;n/=2)
        T[n]=min(T[n<<1],T[n<<1|1]);
}

int Query(int s,int t){
    int minc = INF;
    for(s=s+M-1,t=t+M+1;s^t^1;s/=2,t/=2){
        if(~s&1) minc=min(minc,T[s^1]);
        if(t&1) minc=min(minc,T[t^1]);
    }
    return minc;
}
void Replace(char *ch,int &cur){
    cur = 0; int tmp=0;
    int len = strlen(ch);
    for(int i=0;i<len;i++)
        if(isdigit(ch[i])){
            tmp=tmp*10 + ch[i]-'0';
            if(i+1==len||!isdigit(ch[i+1])){
                q[cur++] = tmp;
                tmp = 0;
            }
        }
}
void solve_question(int m){
    int cur;
    for(int i=0;i<m;i++){
        scanf("%s",ch);
        if(ch[0]=='q'){
            Replace(ch,cur);
            printf("%d
",Query(q[0],q[1]));
        }else{
            Replace(ch,cur);
            int t = a[q[0]];
            for(int i=0;i<cur-1;i++)
                a[q[i]] = a[q[i+1]];
            a[q[cur-1]] = t;
            for(int i=0;i<cur;i++)
                Updata(q[i],a[q[i]]);
        }
    }
}
int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    cnt = 1;
    Build(n);
    solve_question(m);
}
 




原文地址:https://www.cnblogs.com/Pretty9/p/7384052.html