zoukankan      html  css  js  c++  java
  • UVa 12299 RMQ with Shifts(移位RMQ)

    UVa 12299 - RMQ with Shifts(移位RMQ)

    Time limit: 1.000 seconds


    Description - 题目描述

    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

    在经典的RMQ(区间最值)问题中,给定数组A。对于每个询问(L,R) (L ≤ R),输出A[L], A[L + 1], ..., A[R]中的最小值。注意下标从1开始,即最左边的元素为A[1]。在这个问题中,数组A会发生些许变化:定义如下操作
    CN
     
    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.

    我们对A[i1], A[i2], ..., A[ik]执行循环左移。例如,A={6, 2, 4, 8, 5, 1, 4},则经过shift(2,4,5,7)后得到 {6, 8, 4, 5, 4, 1, 2}。再经过shift (1,2)得到8, 6, 4, 5, 4, 1, 2
    CN

     

    Input - 输入

    There will be only one test case, beginning with two integers n, q (1 ≤ n ≤ 100,000, 1 ≤ q ≤ 250,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.

    只有一组测试用例,起始位置有两个整数n, q (1 ≤ n ≤ 100,000, 1 ≤ q ≤ 250,000),分别表示整数数组A中的元素个数,询问的数量。下一行有n个不超过100,000的非负数,皆为数组A中的初始元素。随后q行每行包含一个操作。每个操作皆为一个不超过30个字符的字符串,且不含空格。全部操作均正确有效。
    
    注意:数据量很大,最好使用更快的I/O函数。
    CN

    Output - 输出

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

    对于每个询问,输出待求范围的最小值(非下标)。
    CN

     

    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
    

    题解

    一般的线段树。

    虽然说数据量大,意思也就不能用cin吧,scanf还是可以A的。

    一开始还以为需要用延迟更新,然后想了想30*25WO(NlogN)还是应该可以的,能简则简。

    代码中用的是自下往上的更新方式,目测比从上往下略快,可以跳过部分更新。

    代码 C++

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #define mx 100005
     5 int tr[mx << 2], path[mx], iP, ts[mx];
     6 int build(int L, int R, int now){
     7     if (L > R) return mx;
     8     if (L == R) scanf("%d", tr + (path[++iP] = now));
     9     else{
    10         int mid = L + R >> 1, cL, cR;
    11         cL = build(L, mid, now << 1); cR = build(mid + 1, R, now << 1 | 1);
    12         tr[now] = std::min(cL, cR);
    13     }
    14     return tr[now];
    15 }
    16 int query(int L, int R, int now, int edL, int edR){
    17     if (edL <= L && R <= edR) return tr[now];
    18     int mid = L + R >> 1, cL, cR;
    19     if (edR <= mid) return query(L, mid, now << 1, edL, edR);
    20     if (mid < edL) return query(mid + 1, R, now << 1 | 1, edL, edR);
    21     cL = query(L, mid, now << 1, edL, mid); cR = query(mid + 1, R, now << 1 | 1, mid + 1, edR);
    22     return std::min(cL, cR);
    23 }
    24 void updata(int now, int n){
    25     int tmp, cL, cR;
    26     while (now >>= 1){
    27         tmp = std::min(tr[now << 1], tr[now << 1 | 1]);
    28         if (tmp == tr[now]) return;
    29         tr[now] = tmp;
    30     }
    31 }
    32 int main(){
    33     memset(tr, 127, sizeof(tr));
    34     int n, q, i, j, tmp;
    35     char op[20];
    36     scanf("%d%d", &n, &q);
    37     build(1, n, 1); getchar();
    38     while (q--){
    39         fread(op, sizeof(char), 6, stdin);
    40         if (*op == 'q'){
    41             for (i = 0; i < 2; ++i) scanf("%d", ts + i), getchar();
    42             printf("%d
    ", query(1, n, 1, ts[0], ts[1]));
    43         }
    44         else{
    45             for (j = 0; *op != ')'; ++j) scanf("%d", ts + j), *op = getchar();
    46             for (tmp = tr[path[ts[i = 0]]]; i < j - 1; ++i){
    47                 tr[path[ts[i]]] = tr[path[ts[i + 1]]];
    48                 updata(path[ts[i]], n);
    49             }
    50             tr[path[ts[i]]] = tmp;
    51             updata(path[ts[i]], n);
    52         }
    53         getchar();
    54     }
    55     return 0;
    56 }
  • 相关阅读:
    Python基础语法 第2节课(数据类型转换、运算符、字符串)
    python基础语法 第5节课 ( if 、 for )
    python基础语法 第4节课 (字典 元组 集合)
    Python基础语法 第3节课 (列表)
    A. Peter and Snow Blower 解析(思維、幾何)
    C. Dima and Salad 解析(思維、DP)
    D. Serval and Rooted Tree (樹狀DP)
    C2. Balanced Removals (Harder) (幾何、思維)
    B. Two Fairs 解析(思維、DFS、組合)
    D. Bash and a Tough Math Puzzle 解析(線段樹、數論)
  • 原文地址:https://www.cnblogs.com/Simon-X/p/5995157.html
Copyright © 2011-2022 走看看