UVa 12299 - RMQ with Shifts (简单线段树)

UVA - 12299
Time Limit: 1000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu

[]   [Go Back]   [Status]  

Description

Download as PDF


  RMQ with Shifts 

In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each query (LR) (L$ \le$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

shifti 1i 2i 3,...,  i k)(  i 1 <  i 2 < ... <  i kk > 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$ \le$n$ \le$100, 0001$ \le$q$ \le$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.

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



The Seventh Hunan Collegiate Programming Contest 
Problemsetter: Rujia Liu, Special Thanks: Yiming Li & Jane Alam Jan

Source

Root :: Prominent Problemsetters ::  Rujia Liu

Root :: AOAPC I: Beginning Algorithm Contests -- Training Guide (Rujia Liu) :: Chapter 3. Data Structures :: Maintaining Interval Data :: Exercises: Beginner

[]   [Go Back]   [Status]  




题意:

对于序列A,有两种操作:

query(L,R) 询问[L, R]直接的最小值

shift(k1, k2, k3...) A[k1] A[k2] A[k3] ... 依次循环左移一位



因为shift移动元素很少,所以对于shift直接暴力移动,然后线段树维护最小值就行了

WA了好多次

后来发现移动的代码出了问题 ╮(╯▽╰)╭




#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 1e-9;
const double PI = (4.0*atan(1.0));

const int maxn = 100000 + 20;
const int maxo = maxn * 4;

LL minv[maxo];
LL A[maxn];

void build(int o, int L, int R) {
    if(L == R) {
        minv[o] = A[L];
        return ;
    }
    int M = L + (R-L) / 2;
    build(o*2, L, M);
    build(o*2+1, M+1, R);
    minv[o] = min(minv[o*2], minv[o*2+1]);
}

int qx, qv;
void update(int o, int L, int R) {
    if(L == qx && qx == R) {
        minv[o] = qv;
        return ;
    }
    int M = L + (R-L) / 2;
    if(qx <= M) update(o*2, L, M);
    else update(o*2+1, M+1, R);
    minv[o] = min(minv[o*2], minv[o*2+1]);
}

int ql, qr;
LL query(int o, int L, int R) {
    if(ql <= L && R <= qr) {
        return minv[o];
    }
    int M = L + (R-L) / 2;
    LL res = INF;
    if(ql <= M) res = min(res, query(o*2, L, M));
    if(M < qr) res = min(res, query(o*2+1, M+1, R));
    return res;
}

char str[100];
int move[40];
int getIntegers(char * s) {
    int num = 0;
    int len = strlen(str);
    int p = 0;
    while(p < len) {
        int x = 0;
        while(p < len && (str[p] < '0' || str[p] > '9')) p++;
        while(p<len && str[p] >= '0' && str[p] <= '9') {
            x = x * 10 + str[p] - '0';
            p++;
        }
        if(x) move[num++] = x;
    }
    return num;
}

int main() {
    int n, m;

    while(scanf("%d%d", &n, &m) != EOF) {
        for(int i=1; i<=n; i++) scanf("%lld", &A[i]);
        build(1, 1, n);
        while(m--) {
            scanf("%s", str);
            int num = getIntegers(str);
            if(str[0] == 'q') {
                ql = move[0], qr = move[1];
                LL ans = query(1, 1, n);
                P64I(ans);
            } else {
                for(int i=0; i<num; i++) {
                    qx = move[i];
                    qv = A[move[(i+1)%num]];
                    update(1, 1, n);
                }
                int t = A[move[0]];
                for(int i=0; i<num-1; i++) {
                    A[move[i]] = A[move[i+1]];
                }
                A[move[num-1]] = t;
            }
        }
    }

    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值