RMQ with Shifts 线段树+点修改

本文介绍了一个扩展的传统RMQ问题,即Range Minimum Query问题,并在此基础上加入了数组元素的循环左移操作。通过使用线段树数据结构,文章详细阐述了如何实现对数组的查询和更新操作,包括区间最小值查询和特定位置元素值的更新。
摘要由CSDN通过智能技术生成

RMQ with Shifts 

In the traditional RMQ (Range Minimum Query) problem, we have a static array A. Then for eachquery (L, R) (L$ \le$R), we report the minimum value among A[L],A[L + 1], ..., A[R]. Note that theindices start from 1, i.e. the left-most element isA[1].

In this problem, the array A is no longer static: we need to support another operation

shift( i 1, i 2, i 3,..., i k)( i 1 < i 2 < ... < i k, 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.

Input 

There will be only one test case, beginning with two integers n, q ( 1$ \le$n$ \le$100, 000, 1$ \le$q$ \le$250, 000),the number of integers in array A, and the number of operations. The next line contains n positiveintegers not greater than 100,000, the initial elements in array A. Each of the next q lines contains anoperation. Each operation is formatted as a string having no more than 30 characters, with no spacecharacters 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

解决方案:这题只涉及了基本的线段树点的修改,区间最大值的查询。.。。。忽然发现,代码贴错了,,,,,

code:


<pre name="code" class="cpp">#include<iostream>
#include<cstdio>
#include<cstring>
#define MMAX 100003
using namespace std;
int Min[4*MMAX];
int n,q,_min;
int Q[100],k,x,v;
void push_up(int rt)
{

    int l=rt*2,r=rt*2+1;

    Min[rt]=min(Min[l],Min[r]);


}///往上更新维护数组
void build(int rt,int L,int R)
{

    if(L==R)
    {
        scanf("%d",&Min[rt]);
        // cout<<rt<<endl;
        return ;
    }
    else
    {
        int M=(L+R)/2;
        build(rt*2,L,M);
        build(rt*2+1,M+1,R);
        push_up(rt);
    }

}///线段树的建立
void query(int rt,int L,int R,int l,int r)
{
    if(l<=L&&r>=R)
    {
        _min=min(_min,Min[rt]);
    }
    else
    {
        int M=(L+R)/2;
        if(l<=M) query(rt*2,L,M,l,r);
        if(r>M) query(rt*2+1,M+1,R,l,r);
    }

}///区间查询
void update(int rt,int L,int R)
{

    if(L==R)
    {
        Min[rt]=v;
    }
    else
    {
        int M=(L+R)/2;
        if(Q[x]<=M)
        {
            update(rt*2,L,M);
        }
        else update(rt*2+1,M+1,R);
        Min[rt]=min(Min[rt*2],Min[rt*2+1]);
    }
}///单点修改
void getnum(char str[])
{

    int len=strlen(str);
    k=0;
    for(int i=6; i<len-1; i++)
    {
        if(str[i]==',')
        {
            k++;
            continue;
        }
        Q[k]*=10;
        Q[k]+=str[i]-'0';
    }

}
int main()
{
    char str[40];
    while(~scanf("%d%d",&n,&q))
    {
        build(1,1,n);
        for(int i=0; i<q; i++)
        {
            memset(Q,0,sizeof(Q));
            scanf("%s",str);
            getnum(str);
            if(str[0]=='q')
            {
                _min=MMAX;
                query(1,1,n,Q[0],Q[1]);
                printf("%d\n",_min);
            }
            else
            {
                int temp;
                _min=MMAX;
                query(1,1,n,Q[k],Q[k]);
                temp=_min;
                _min=MMAX;
                query(1,1,n,Q[0],Q[0]);
                //  cout<<k<<endl;
                x=k,v=_min;
                //  cout<<v<<endl;
                update(1,1,n);
                for(x=0; x<k-1; x++)
                {
                    _min=MMAX;
                    query(1,1,n,Q[x+1],Q[x+1]);
                    v=_min;
                    update(1,1,n);
                }
                x=k-1;
                v=temp;
                update(1,1,n);


            }

        }
    }




    return 0;
}



                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值