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;
}
时间: 2024-10-27 07:44:09

CodeForces 52C Circular RMQ的相关文章

CodeForces 52C Circular RMQ(区间循环线段树,区间更新,区间求和)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://codeforces.com/problemset/problem/52/C You are given circular array a0,?a1,?...,?an?-?1. There are two types of operations with it: inc(lf,?rg,?v) - this operation increases each element on the segm

CF#52 C Circular RMQ (线段树区间更新)

Description You are given circular array a0,?a1,?...,?an?-?1. There are two types of operations with it: inc(lf,?rg,?v) - this operation increases each element on the segment [lf,?rg] (inclusively) by v; rmq(lf,?rg) - this operation returns minimal v

「CF52C」Circular RMQ

更好的阅读体验 Portal Portal1: Codeforces Portal2: Luogu Description You are given circular array \(a_0, a_1, \cdots, a_{n - 1}\). There are two types of operations with it: \(\textrm{inc}(lf, rg, v)\) - this operation increases each element on the segment

【CF52C】Circular RMQ

给定一个循环数组a0, a1, a2, …, an-1,现在对他们有两个操作: Inc(le, ri, v):表示区间[le, ri]范围的数值增加v Rmq(le, ri):表示询问区间[le, ri]范围内的最小值 注意,这个是循环数组,所以如果n=5, le=3, ri=1,那么询问的是a3, a4, a0, a1中的最小值. 帮助BSNY写一个程序完成上述操作. 挖坑待填.

Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树

思路: (我也不知道这是不是正解) ST表预处理出来原数列的两点之间的min 再搞一个动态开节点线段树 节点记录ans 和标记 lazy=-1 当前节点的ans可用  lazy=0 没被覆盖过 else 区间覆盖 push_up的时候要注意好多细节,, 数组尽量往大开 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const in

CodeForces 279C Ladder (RMQ + dp)

题意:给定一个序列,每次一个询问,问某个区间是不是先增再降的. 析:首先先取处理以 i 个数向左能延伸到哪个数,向右能到哪个数,然后每次用RQM来查找最大值,分别向两边延伸,是否是覆盖区间. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <c

CodeForces 475D CGCDSSQ RMQ

通过这道题目还是学到了不少东西的,当时刚拿到这个题目的时候时间已经不多了,因为前面有个C坑到了,看了个大概,然后就往线段树和树状数组方面去想了,对于gcd的区间求一个前缀,再搞一个后缀 瞎弄弄,后来发现错了,题目求的是区间个数...又浪费了一段时间,然后回头再看看,大致就想到了暴力枚举,n是10^5,大不了离线先暴力的高出答案,想到一般发现  若假定一个询问输入的数 为  X,那么另一个 能够 y 通过gcd(x,y)得到的另一个数的 答案就是它自身的答案数再加上当前x的答案数,这样就有递推了,

CF52C Circular RMQ

题目链接 思路: 这道题其实还是普通的区间修改和查询问题,只不过序列变为了环形,所以就是小小的改一下就可以了. 分类讨论一下,如果输入的l<r,那么就是照常修改和查询.但由于是环形,所以会出现l>r的地方,其实也就是这样拆成l-n和1-r两个操作即可. 代码,不需要代码,太水了 #include<bits/stdc++.h> using namespace std; const int maxn=1e6+7; struct node{ int l,r; long long lazy

(WAWAWAWAWAWAW) G. Periodic RMQ Problem

没有联通门 : Codeforces G. Periodic RMQ Problem /* Codeforces G. Periodic RMQ Problem MMP 什么动态开点线段树啊 ... YY了个非常可行的做法 码完后交一下发现RE了几个点.. 就思考哪里有问题 突然之间, 老泪纵横.. MMP 我写了这是个什么玩意啊 仔细想想我TM不就是写了个全空间的主席树吗....脑子有病啊.. 静言思之, 躬自悼矣..反是不思,亦已焉哉 不写啦! */ #include <cmath> #i