zoukankan      html  css  js  c++  java
  • 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);
    }
     




  • 相关阅读:
    BestCoder17 1001.Chessboard(hdu 5100) 解题报告
    codeforces 485A.Factory 解题报告
    codeforces 485B Valuable Resources 解题报告
    BestCoder16 1002.Revenge of LIS II(hdu 5087) 解题报告
    codeforces 374A Inna and Pink Pony 解题报告
    codeforces 483B Friends and Presents 解题报告
    BestCoder15 1002.Instruction(hdu 5083) 解题报告
    codeforces 483C.Diverse Permutation 解题报告
    codeforces 483A. Counterexample 解题报告
    NSArray中地内存管理 理解
  • 原文地址:https://www.cnblogs.com/Pretty9/p/7384052.html
Copyright © 2011-2022 走看看