CF 52C Circular RMQ(区间更新,区间询问)

Circular RMQ
time limit per test
3 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 value on the segment [lf, rg] (inclusively).

Assume segments to be circular, so if n = 5 and lf = 3, rg = 1, it means the index sequence: 3, 4, 0, 1.

Write program to process given sequence of operations.

Input

The first line contains integer n (1 ≤ n ≤ 200000). The next line contains initial state of the array: a0, a1, ..., an - 1 ( - 106 ≤ ai ≤ 106), ai are integer. The third line contains integer m (0 ≤ m ≤ 200000), m — the number of operartons. Next m lines contain one operation each. If line contains two integer lf, rg (0 ≤ lf, rg ≤ n - 1) it means rmq operation, it contains three integers lf, rg, v (0 ≤ lf, rg ≤ n - 1; - 106 ≤ v ≤ 106) — inc operation.

Output

For each rmq operation write result for it. Please, do not use %lld specificator to read or write 64-bit integers in C++. It is preffered to use cout (also you may use %I64d).

Sample test(s)
Input
4
1 2 3 4
4
3 0
3 0 -1
0 1
2 1
Output
1
0
0
 
   
题意:给出n个数,m次操作,操作有[a,b]区间每个数加上c或者求[a,b]区间的最小值。
思路:线段树。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <vector>
#include <cmath>
#include <stack>
#include <cstdlib>
#define L(rt) (rt<<1)
#define R(rt) (rt<<1|1)

using namespace std;

const int maxn=200005;
struct node
{
    int l,r;
    long long add,ans;
}tree[maxn*4];
int num[maxn];
int n;
void build(int l,int r,int rt)
{
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].add=0;
    if(l==r)
    {
        tree[rt].ans=num[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,L(rt));
    build(mid+1,r,R(rt));
    tree[rt].ans=min(tree[L(rt)].ans,tree[R(rt)].ans);
}
void update(int l,int r,int rt,int val)
{
    if(tree[rt].l==l&&tree[rt].r==r)
    {
        tree[rt].ans+=val;
        tree[rt].add+=val;
        return;
    }
    if(tree[rt].add)
    {
        tree[L(rt)].ans+=tree[rt].add;
        tree[L(rt)].add+=tree[rt].add;
        tree[R(rt)].ans+=tree[rt].add;
        tree[R(rt)].add+=tree[rt].add;
        tree[rt].add=0;
    }
    if(r<=tree[L(rt)].r) update(l,r,L(rt),val);
    else if(l>=tree[R(rt)].l) update(l,r,R(rt),val);
    else
    {
        update(l,tree[L(rt)].r,L(rt),val);
        update(tree[R(rt)].l,r,R(rt),val);
    }
    tree[rt].ans=min(tree[L(rt)].ans,tree[R(rt)].ans);
}
long long query(int l,int r,int rt)
{
    if(tree[rt].l==l&&tree[rt].r==r)
    return tree[rt].ans;
    if(tree[rt].add)
    {
        tree[L(rt)].ans+=tree[rt].add;
        tree[L(rt)].add+=tree[rt].add;
        tree[R(rt)].ans+=tree[rt].add;
        tree[R(rt)].add+=tree[rt].add;
        tree[rt].add=0;
    }
    if(r<=tree[L(rt)].r) return query(l,r,L(rt));
    else if(l>=tree[R(rt)].l) return query(l,r,R(rt));
    else return min(query(l,tree[L(rt)].r,L(rt)),query(tree[R(rt)].l,r,R(rt)));
}
int main()
{
    char ch;
    int a,b,c,m,ans;
    while(cin>>n)
    {
        for(int i=1;i<=n;i++)
        cin>>num[i];
        build(1,n,1);
        cin>>m;
        while(m--)
        {
            int flag=0;
           cin>>a>>b;
           if((ch=getchar())==' ')
           {
               flag=1;
               cin>>c;
           }
           a++;
           b++;
           if(!flag)
           {
               if(b>=a) ans=query(a,b,1);
               else
               ans=min(query(a,n,1),query(1,b,1));
               cout<<ans<<endl;
           }
           else
           {
               if(b>=a) update(a,b,1,c);
               else
               {
                   update(a,n,1,c);
                   update(1,b,1,c);
               }
           }
        }
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值