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 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 Input

Input

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

Output

1
0
0

题意很好理解。

如果a>b的话,就查0~b和a~n-1,其余的就是线段树区间更新模板,判断m个询问里是否存在c,详见代码,很好理解。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
#include <ctype.h>
#include <iostream>
#define lson o << 1, l, m
#define rson o << 1|1, m+1, r
using namespace std;
typedef __int64 LL;
const __int64 MAX =  9223372036854775807;
const int maxn = 200010;
int n, a, q, c, b;
char str[1200];
LL mi[maxn<<2], add[maxn<<2];
void up(int o) {
    mi[o] = min(mi[o<<1], mi[o<<1|1]);
}
void down(int o) {
    if(add[o]) {
        add[o<<1] += add[o];
        add[o<<1|1] += add[o];
        mi[o<<1] += add[o];
        mi[o<<1|1] += add[o];
        add[o] = 0;
    }
}
void build(int o, int l, int r) {
    if(l == r) {
        scanf("%I64d", &mi[o]);
        return;
    }
    int m = (l+r) >> 1;
    build(lson);
    build(rson);
    up(o);
}
void update(int o, int l, int r) {
    if(a <= l && r <= b) {
        add[o] += c;
        mi[o] += c;
        return ;
    }
    down(o);
    int m = (l+r) >> 1;
    if(a <= m) update(lson);
    if(m < b ) update(rson);
    up(o);
}
LL query(int o, int l, int r) {
    if(a <= l && r <= b) return mi[o];
    down(o);
    int m = (l+r) >> 1;
    LL res = MAX;
    if(a <= m) res = query(lson);
    if(m < b ) res = min(res, query(rson));
    return res;
}
int main()
{
    scanf("%d", &n);
    build(1, 0, n-1);
    scanf("%d", &q); getchar(); while(q--) {
        gets(str);
        if(sscanf(str,"%d %d %d", &a, &b, &c) == 3)  {
            if(a <= b) update(1, 0, n-1);
            else {
                int tmp = b;
                b = n-1; update(1, 0, n-1);
                a = 0, b = tmp; update(1, 0, n-1);
            }
        } else {
            LL ans ;
            if(a <= b) ans = query(1, 0, n-1);
            else {
                int tmp = b;
                b = n-1; ans = query(1, 0, n-1);
                a = 0, b = tmp; ans = min(ans, query(1, 0, n-1));
            }
            printf("%I64d\n", ans);
        }
    }
    return 0;
}



CF#52 C Circular RMQ (线段树区间更新),布布扣,bubuko.com

时间: 2024-12-25 20:05:02

CF#52 C Circular RMQ (线段树区间更新)的相关文章

POJ 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

Hdu 3966 Aragorn&#39;s Story (树链剖分 + 线段树区间更新)

题目链接: Hdu 3966 Aragorn's Story 题目描述: 给出一个树,每个节点都有一个权值,有三种操作: 1:( I, i, j, x ) 从i到j的路径上经过的节点全部都加上x: 2:( D, i, j, x ) 从i到j的路径上经过的节点全部都减去x: 3:(Q, x) 查询节点x的权值为多少? 解题思路: 可以用树链剖分对节点进行hash,然后用线段树维护(修改,查询),数据范围比较大,要对线段树进行区间更新 1 #include <cstdio> 2 #include

HDU 5023 A Corrupt Mayor&#39;s Performance Art 线段树区间更新+状态压缩

Link:  http://acm.hdu.edu.cn/showproblem.php?pid=5023 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <string> 7 #include <cmath> 8 using namesp

HDU 5023 A Corrupt Mayor&#39;s Performance Art(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色,有两种操作: P a b c  把区间a到b涂成c颜色 Q a b 查询区间a到b的颜色 线段树区间更新,每个节点保存的信息有,存储颜色的c,30种颜色可以压缩到一个int型里面存储,然后还有一个tot,表示这个区间一共有多少种颜色. 对于P操作,依次往下寻找,找要更新的区间,找到要更新的区间之前

HDU 4902 Nice boat(线段树 区间更新)

Nice boat 大意:给你一个区间,每次可以进行两种操作,1:把区间中的数全都变成x  2:把区间中大于x的数变成gcd(a[i], x),最后输出序列. 思路:线段树成段更行,用num数组的叶子存储数据,节点当作lazy来使用. 1 #include <stdio.h> 2 const int maxn = 100005; 3 4 int num[maxn<<2]; 5 6 int gcd(int a, int b){ 7 return b?gcd(b, a%b):a; 8

HDU-------(2795)Billboard(线段树区间更新)

Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10594    Accepted Submission(s): 4686 Problem Description At the entrance to the university, there is a huge rectangular billboard of s

线段树 区间更新

poj3468 A Simple Problem with Integers ( m - ( m >> 1 ) )这里跪了几发.. - 的优先级大于 >> 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<string> 6 #include<queue> 7 #include

HDU 1698 Just a Hook (线段树,区间更新)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 17214    Accepted Submission(s): 8600 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f

hdu----(5023)A Corrupt Mayor&#39;s Performance Art(线段树区间更新以及区间查询)

A Corrupt Mayor's Performance Art Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others)Total Submission(s): 33    Accepted Submission(s): 11 Problem Description Corrupt governors always find ways to get dirty money. Pa