UVA 12299

  RMQ with Shifts 

In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for each query (LR)(LR), 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( i 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  n q  (   1n100, 000 1q250, 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

运用线段树的查询区间最值和单点修改。

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


using namespace std;
//#define Online_Judge
#define outstars cout << "***********************" << endl;
#define clr(a,b) memset(a,b,sizeof(a))

#define FOR(i , x , n) for(int i = (x) ; i < (n) ; i++)
#define FORR(i , x , n) for(int i = (x) ; i <= (n) ; i++)
#define REP(i , x , n) for(int i = (x) ; i > (n) ; i--)
#define REPP(i ,x , n) for(int i = (x) ; i >= (n) ; i--)
const int MAXN = 100000 + 50;
const int maxw = 100 + 20;
const int MAXNNODE = 1000000 +10;
const long long LLMAX = 0x7fffffffffffffffLL;
const long long LLMIN = 0x8000000000000000LL;
const int INF = 0x7fffffff;
const int IMIN = 0x80000000;
#define eps 1e-8
#define mod 1000000007
typedef long long LL;
const double PI = acos(-1.0);
typedef double D;
typedef pair<int , int> pi;
struct Node
{
    int left;
    int right;
    int minx;
};
int n , q ;
Node node[4*MAXN];/*最多需要分配的空间*/
int number[MAXN];

//向上更新
void push_up(int pos)
{
    node[pos].minx = min(node[pos<<1].minx , node[(pos<<1)+1].minx);/*向上更新当前点的信息*/
}

/*建立空的二叉树,初始化每个营地人数为0*/
void buildTree(int left , int right , int pos)
{
    node[pos].left = left;
    node[pos].right = right;
    if(left == right)
    {
        node[pos].minx = number[left];
        return;
    }
    /*递归建立子树*/
    int mid = (left+right)>>1;
    buildTree(left , mid , pos<<1);
    buildTree(mid+1 , right , (pos<<1)+1);
    push_up(pos);
}

/*单点更新*/
void update(int p , int d , int l , int r ,int pos)
{
    if(l == r)
    {
        number[l] = d;
        node[pos].minx = d;
        return;
    }
    int m = (l + r) >> 1;
    if(p <= m)update(p , d , l , m , pos << 1);
    else update(p , d , m + 1 , r ,(pos << 1) + 1);
    push_up(pos);
}
int query(int ql,int qr,int l,int r,int s)
{
    if(ql <= l&&r <= qr)
        return node[s].minx;
    int m = (l + r)>>1,ans=INF;
    if(ql <= m) ans = min(ans,query(ql , qr , l , m , s << 1));
    if(qr > m) ans = min(ans,query(ql , qr , m + 1 , r , (s << 1) + 1));
    return ans;
}
char s[35];
vector<int> V , A;
int main()
{
    //ios::sync_with_stdio(false);
#ifdef Online_Judge
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif // Online_Judge
    while(scanf("%d%d", &n ,&q) == 2)
    {
        FORR(i , 1 , n)scanf("%d" , &number[i]);
        buildTree(1 , n , 1);
        while(q--)
        {
            scanf("%s" , s);
            int len = strlen(s);
            if(s[0] == 'q')
            {
                int a = 0;
                int b = 0;
                int i  = 4;
                while(s[i] != ',')
                {
                    if(isdigit(s[i]))
                    {
                        a = a * 10 + s[i] -'0';
                    }
                    i++;
                }
                while(i < len)
                {
                    if(isdigit(s[i]))
                    {
                        b = b * 10 + s[i] - '0';
                    }
                    i++;
                }
                printf("%d\n" , query(a , b , 1 , n ,1));
            }
            else
            {
                int i = 4;
                V.clear();
                A.clear();
                while(i < len)
                {
                    int a = 0;
                    while(s[i] != ','&&s[i] != ')')
                    {
                        if(isdigit(s[i]))
                        {
                            a = a * 10 + s[i] - '0';
                        }
                        i++;
                    }
                    i++;
                    V.push_back(a);
                    A.push_back(number[a]);
                }
                int b = A[0];
                A.erase(A.begin());
                A.push_back(b);
                FOR(k , 0 , V.size())update(V[k] , A[k] , 1 , n , 1);
            }
        }
    }
    return 0;
}


UVA的第150题!Mark一下,继续加油!

你可能感兴趣的:(线段树,ACM)