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);
    }
     




  • 相关阅读:
    hdu 4027 Can you answer these queries? 线段树
    ZOJ1610 Count the Colors 线段树
    poj 2528 Mayor's posters 离散化 线段树
    hdu 1599 find the mincost route floyd求最小环
    POJ 2686 Traveling by Stagecoach 状压DP
    POJ 1990 MooFest 树状数组
    POJ 2955 Brackets 区间DP
    lightoj 1422 Halloween Costumes 区间DP
    模板 有源汇上下界最小流 loj117
    模板 有源汇上下界最大流 loj116
  • 原文地址:https://www.cnblogs.com/Pretty9/p/7384052.html
Copyright © 2011-2022 走看看