CodeForces 52C Circular RMQ (线段树)

线段树区间更新维护最小值。。。记得下放标记。。。

如果线段树上的一个完整区间被修改,那么最小值和最大值增加相应的值后不变,

会改变是因为一部分改变而另外一部分没有改变所以维护一下就好。

询问的时候也要记得下放标记。。。

数据结构快忘了,贴个板。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+1;

struct Seg
{
    ll lazy;
    ll Min;
}tr[maxn<<2];

int a[maxn];
int n;

#define lid (id<<1)
#define rid (id<<1|1)

void build(int l = 0,int r = n-1,int id = 1)
{
    if(l == r) { tr[id].Min = a[l]; return; }//tr[rt].lazy }
    int mid = (l+r)>>1, lc = lid, rc = rid;
    build(l,mid,lc);
    build(mid+1,r,rc);
    tr[id].Min = min(tr[lc].Min,tr[rc].Min);
}

int ql,qr;
ll val;

#define Modify(id,v) tr[id].lazy += v; tr[id].Min += v;
void updata(int l = 0,int r = n-1,int id = 1)
{
    if(ql<=l&&r<=qr) { Modify(id,val)  return; }
    int mid = (l+r)>>1, lc = lid, rc = rid;
    if(tr[id].lazy){
        ll &t = tr[id].lazy;
        Modify(lc,t)
        Modify(rc,t)
        t = 0;
    }
    if(ql<=mid){
        updata(l,mid,lc);
    }
    if(qr>mid) {
        updata(mid+1,r,rc);
    }
    tr[id].Min = min(tr[lc].Min,tr[rc].Min);
}

const ll INF = 0x3f3f3f3f3f3f3f3f;

ll query(int l = 0,int r = n-1,int id = 1)
{
    if(ql<=l&&r<=qr){
        return tr[id].Min;
    }
    int mid = (l+r)>>1,lc = lid, rc = rid;
    if(tr[id].lazy){
        ll &t = tr[id].lazy;
        Modify(lc,t);
        Modify(rc,t);
        t = 0;
    }
    ll ret = INF;
    if(ql<=mid){
        ret = min(ret,query(l,mid,lc));
    }
    if(qr>mid){
        ret = min(ret,query(mid+1,r,rc));
    }
    return ret;
}

bool sscan_l(int &x,char *&s)
{
    while(!isdigit(*s) && *s != '-'){
        if(!*s) return false;
        s++;
    }
    bool fg;
    if(*s == '-') fg = true,x = 0;
    else x = *s-'0',fg = false;

    while(s++,isdigit(*s)) x = x*10+*s-'0';
    if(fg) x = -x;
    return true;
}

char Line[666];
int main()
{
    //freopen("in.txt","r",stdin);
    scanf("%d",&n);
    for(int i = 0; i < n; i++) scanf("%d",a+i);
    build();
    int m; scanf("%d\n",&m);
    while(m--){
        gets(Line);
        char *p = Line;
        int num[3], i;
        for(i = 0; i < 3; i++ ){
            if(!sscan_l(num[i],p)) break;
        }
        if(i == 2){
            int l = num[0],r = num[1];
            if(l<=r) {
                ql = l; qr = r;
                printf("%I64d\n",query());
            }else {
                ql = 0; qr = r;
                ll ans = query();
                ql = l; qr = n-1;
                ans = min(ans,query());
                printf("%I64d\n",ans);
            }
        }else {
            int l = num[0], r = num[1]; val = num[2];
            if(l<=r){
                ql = l; qr = r;
                updata();
            }else {
                ql = 0; qr = r;
                updata();
                ql = l; qr = n-1;
                updata();
            }
        }
    }
    return 0;
}

 

posted @ 2015-09-05 19:55  陈瑞宇  阅读(228)  评论(0编辑  收藏  举报