UVA12299 - RMQ with Shifts(线段树)

题目链接

题目大意:要求你查询某一段的最小值,但是还有一个shift操作,将(a0, a1, a2, a3..ak)这个K个位置的数字互相对掉,例如a0位置的值变成a1,a1位置的值变成a2...ak位置的值变成a0.

解题思路:因为shift后面的操作数最多30个,所以可以用线段树单点修改。复杂度n*logn。用sscanf函数挺耗时的,还是自己写处理函数。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 1e5 + 5;
const int M = 35;
const int INF = 0x3f3f3f3f;

int n, q;
int v[4 * N];
int A[N];
int s[M], num[M];

int Query (int o, int l, int r, int ql, int qr) {

    int m = l + (r - l)/ 2;
    int ans = INF; 

    if (ql <= l && r <= qr)
        return v[o];

    if (ql <= m)
        ans = min (ans, Query (2 * o, l, m, ql, qr));
    if (qr > m)
        ans = min (ans, Query (2 * o + 1, m + 1, r, ql, qr));
    return ans;
}

void Update (int o, int l, int r, int p, int val) {

    int m = l + (r - l) / 2;
    if (l == r)
        v[o] = val;
    else {

        if (p <= m)
            Update (2 * o, l, m, p, val);
        else
            Update (2 * o + 1, m + 1, r, p, val);
        v[o] = min (v[2 * o] , v[2 * o + 1]);
    }
}

int get_number (char* str) {

    int dex = 0;
    int len = strlen (str);
    s[dex] = 0;
    bool flag = 0;
    for (int i = 0; i < len; i++) {
        if (str[i] >= ‘0‘ && str[i] <= ‘9‘) {
            s[dex] = s[dex] * 10 + str[i] - ‘0‘;
            flag = 1;
        } else if (flag)
            s[++dex] = 0;
    }
    return dex;
}

void solve () {

    char str[N];
    int x, y;
    while (q--) {

        scanf ("%s", str);
        int dex = get_number(str);
        if (str[0] == ‘q‘) {

            //memcpy (str, str + 6, sizeof (str));
            //sscanf (str, "%d,%d", &x, &y);
            printf ("%d\n", Query (1, 1, n, s[0], s[1]));
        } else {

        /*    memcpy (str, str + 6, sizeof (str));
            sscanf (str, "%d%s", &s[dex], str);
            num[dex++] = A[s[dex]];
            while (sscanf (str, ",%d%s", &s[dex], str)) {
                num[dex++] = A[s[dex]];
            }*/

            for (int i = 0; i < dex; i++)
                num[i] = A[s[i]];

            for (int i = 0; i < dex; i++) {

                if (i + 1 < dex)
                    A[s[i]] = num[i + 1];
                else
                    A[s[i]] = num[0];
                Update (1, 1, n, s[i], A[s[i]]);
            }
        }
    }
}

int main () {

    while (scanf ("%d%d", &n, &q) != EOF) {

        memset (v, 0, sizeof (v));
        for (int i = 1; i <= n; i++) {
            scanf ("%d", &A[i]);
            Update (1, 1, n, i, A[i]);
        }

        solve();
    }
    return 0;
}
时间: 2024-12-04 10:08:25

UVA12299 - RMQ with Shifts(线段树)的相关文章

UVa 12299 RMQ with Shifts(线段树)

线段树,没了.. ----------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cctype> #define rep(i,n) for(int i=0;i<n

hdu1823 Luck and Love 二维RMQ(二维线段树)

题意:给定你二维范围,找这个范围里面的最大值 解题思路:二维线段树有两种实现方式,一种是  树套树  ,另一种则是将二维平面分成4块的  完全四叉树 我的代码: // File Name: 1823.cpp // Author: darkdream // Created Time: 2014年07月10日 星期四 09时38分05秒 #include<vector> #include<list> #include<map> #include<set> #in

POJ 3368 Frequent values RMQ ST算法/线段树

                                                     Frequent values Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15229   Accepted: 5550 Description You are given a sequence of n integers a1 , a2 , ... , an in non-decreasing order. In

蓝书4.1-4.4 树状数组、RMQ问题、线段树、倍增求LCA

这章的数据结构题很真实 T1 排队 bzoj 1699 题目大意: 求静态一些区间的最大值-最小值 思路: ST表裸题 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<v

线段树——忠诚——洛谷——1816

本次的目的主要在于练一练线段树的模板. 这题做法颇多,可以RMQ也可以线段树 #include<iostream> #include<cstdio> using namespace std; inline int read(){ int t=1,num=0;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();} while(c>='0'&&c<='9'){num=n

湖南省第七届大学生计算机程序设计竞赛 RMQ with Shifts (线段树)

RMQ with Shifts 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述     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 indic

Uva 12299 RMQ with Shifts(线段树 + 单点更新 )

Uva 12299 RMQ with Shifts (线段树 + 单点更新) 题意: 对于给定的序列 x[i]给出一个操作 shift(a,b,c,d,e) 对应的是将 x[a]与x[b] x[b]与x[c] 这样相邻的两两交换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

HDU 1754 - I Hate It &amp; UVA 12299 - RMQ with Shifts - [单点/区间修改、区间查询线段树]

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1754 Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感.不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问.当然,老师

nyoj 568——RMQ with Shifts——————【线段树单点更新、区间求最值】

RMQ with Shifts 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述     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 indic