Codeforces 52C - Circular RMQ - 线段树

【题目大意】

给出环形数列a_0,a_1,...,a_n-1。它有两种操作:

inc(lf,rg,v)这个操作使[lf,rg]区间内的每一个值增加v;

rmq(lf,rg)这个操作返回[lf,rg]区间内的最小值。

假设区间是环形的,所以当n=5,lf=3,rg=1时,表示的序列编号为:3,4,0,1。

请编写程序执行这一系列操作。

【输入】

第一行有一个整数n。

第二行为数列的初始状态a_0,a_1,...,a_n-1,a_i是整数。

第三行有一个整数m,表示操作次数。

接下来m行每行为一个操作。如果该行有两个整数lf,rg表示rmq操作,如果该行有三个整数lf,rg,v表示inc操作。

【输出】

对于每个rmq操作输出一行答案

【样例】

输入

4
1 2 3 4
4
3 0
3 0 -1
0 1
2 1

输出

1

0

0

【数据规模】

1<=n<=200000

-10^6<=a_i,v<=10^6

0<=m<=200000

0<=lf,rg<=n-1

【分析】

很明显这是一个在线查询区间、修改区间的问题,可以用线段树解决。由于数列是环形的,在处理操作时要判断如果lf大于rg就拆分成[lf,n-1]和[0,rg]两个区间。输入的时候可以通过sscanf来判断读入的个数。

思路很明显:直接线段树区间修改,并且用线段树查询RMQ,第一次写不带结构体的线段树,这样写起来确实很方便,不过出好多错误,最后对照着别人的代码写。。。。。。。这样也WA了4、5次,乱改了一通过了。。T_T

以后就慢慢使用这样写线段树吧。。挺好用的。。


 

/******************************
* author :crazy_石头
* data structure: 线段树
* created time:2013/11/4 19:53
* Pro:CF 52C-Circular RMQ-线段树
* Judge Status:Accepted
* Memory:9400K
* Time:468MS
*******************************/

#include
#include
#include
#include
#include

using namespace std;

#define rep(i,h,n) for(int i=(h);i<=(n);i++)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll __int64
const int maxn=200000+5;

int n,m,color[maxn<<2],minn[maxn<<2],a[maxn<<2];

inline int min(int a,int b)
{
    return a }

inline void pushup(int rt)
{
    minn[rt]=min(minn[rt<<1],minn[rt<<1|1]);
}

inline void pushdown(int rt)
{
    if(color[rt])
    {
        color[rt<<1]+=color[rt];
        color[rt<<1|1]+=color[rt];
        minn[rt<<1]+=color[rt];
        minn[rt<<1|1]+=color[rt];
        color[rt]=0;
    }
}

inline void build(int l,int r,int rt)
{
    color[rt]=0;
    if(l==r)
    {
        minn[rt]=a[l];
        return ;
    }
    int mid=(l+r)>>1;

    build(lson);
    build(rson);
    pushup(rt);
}

inline void update(int l,int r,int rt,int L,int R,int value)
{
    if(L<=l&&r<=R)
    {
        color[rt]+=value;
        minn[rt]+=value;
        return ;
    }

    int mid=(l+r)>>1;
    pushdown(rt);

    if(L<=mid)
        update(lson,L,R,value);
    if(R>mid)
        update(rson,L,R,value);

    pushup(rt);
}

inline int query(int l,int r,int rt,int L,int R)
{
    if(L<=l&&r<=R)
    {
        return minn[rt];
    }
    pushdown(rt);
    int res=1<<30;
    int mid=(l+r)>>1;
    if(L<=mid)
        res=query(lson,L,R);
    if(R>mid)
        res=min(res,query(rson,L,R));
    return res;
}

int main()
{
    int i,j,n,l,r,w;
    char str[300];
    while(scanf("%d",&n)!=EOF)
    {
        rep(i,0,n-1)
            scanf("%d",&a[i]);
        build(0,n-1,1);
        scanf("%d",&m);
        getchar();
        rep(i,1,m)
        {
            gets(str);
            if(sscanf(str,"%d%d%d",&l,&r,&w)==2)
            {
                if(l>r)
                {
                    int ret=min(query(0,n-1,1,0,r),query(0,n-1,1,l,n));
                    printf("%d\n",ret);
                }
                else
                    printf("%d\n",query(0,n-1,1,l,r));
            }
            else if(l>r)
            {
                update(0,n-1,1,0,r,w);
                update(0,n-1,1,l,n,w);
            }
            else
                update(0,n-1,1,l,r,w);
        }
    }
    return 0;
}

* This source code was highlighted by YcdoiT. ( style: Codeblocks )

你可能感兴趣的:(ACM_数据结构)