UVa:12299 RMQ with Shifts

线段树单点修改+区间最值。

其中shift的操作,只需要挨个改值就行了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#define ll  long long
#define INF 2139062143
#define inf -2139062144
#define MOD 20071027
#define MAXN  500005
#define LEN 111111<<2
using namespace std;
struct Segment_tree
{
    int _min[LEN];
    int ql,qr,sz,sp,sv;
private:

    void pushup(int o)
    {
        _min[o]=min(_min[o<<1],_min[o<<1|1]);
    }
    void myupdate(int o,int L,int R)
    {
        if(L==R) _min[o]=sv;
        else
        {
            int M=(L+R)>>1;
            if(sp<=M)  myupdate(o<<1,L,M);
            else myupdate(o<<1|1,M+1,R);
            pushup(o);
        }
    }
    void mybuild(int o,int L,int  R)
    {
        if(L==R)  scanf("%d",&_min[o]);
        else
        {
            int M=(L+R)>>1;
            mybuild(o<<1,L,M);
            mybuild(o<<1|1,M+1,R);
            pushup(o);
        }
    }
    int myquery(int o,int L,int R)
    {
        if(ql<=L&&R<=qr) return _min[o];
        int M=(L+R)>>1;
        int res=INF;
        if(ql<=M) res=min(res,myquery(o<<1,L,M));
        if(M<qr) res=min(res,myquery(o<<1|1,M+1,R));
        return res;
    }
public:
    void clear(int n)
    {
        sz=n;

        int len=n<<2;
        for(int i=0; i<len; ++i)
         _min[i]=INF;
       // memset(_min,0x7f,sizeof(_min));
    }
    void build()
    {
        mybuild(1,1,sz);
    }
    void update(int p,int v)
    {
        sp=p;
        sv=v;
        myupdate(1,1,sz);
    }
    int query(int L,int R)
    {
        ql=L;
        qr=R;
        return myquery(1,1,sz);
    }
};
Segment_tree tree;
int arr[200];
char str[35];
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int t;
        tree.clear(n);
        tree.build();

        for(int i=1; i<=m; ++i)
        {
            scanf("%s",str);
            if(str[0]=='q')
            {
                int x,y;
                sscanf(str,"query(%d,%d)",&x,&y);
                printf("%d\n",tree.query(x,y));
            }
            else if(str[0]=='s')
            {
                int val=0,k=0;
                for(int i=6; str[i]; ++i)
                {
                    if(isdigit(str[i])) val=val*10+str[i]-'0';
                    else
                    {
                        arr[k++]=val;
                        val=0;
                    }
                }
                int temp=tree.query(arr[0],arr[0]);
                for(int i=1; i<k; ++i)
                {

                    int v=tree.query(arr[i],arr[i]);
                    tree.update(arr[i-1],v);
                }
                tree.update(arr[k-1],temp);
            }
        }
    }
    return 0;
}


 

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