Circular RMQ

2024-03-29 02:58
文章标签 rmq circular

本文主要是介绍Circular RMQ,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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 1

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

思路:

树形结构。

数据较大时可以使用位运算。

以及注意命令的判断。

#include<iostream>
using namespace std;
typedef long long LL;
const LL INF = 0x3fffffff;
struct ss
{LL v,tag;
}a[200000 << 2];
LL Min(LL a,LL b)
{return a < b ? a:b;
}void pushup(int cur)
{a[cur].v = Min(a[cur<<1].v,a[cur<<1|1].v);
}void built(int l,int r,int cur)
{a[cur].v = 0;a[cur].tag = 0;if(l == r){scanf("%I64d", &a[cur].v);return ;}int mid = (l + r) >> 1;built(l, mid,cur << 1);built(mid + 1,r,cur << 1|1);pushup(cur);
}void pushdown(int cur)
{if(a[cur].tag != 0){a[cur<<1].tag += a[cur].tag;a[cur<<1|1].tag += a[cur].tag;a[cur<<1].v += a[cur].tag;a[cur<<1|1].v += a[cur].tag;a[cur].tag = 0;}
}void update(int l,int r,int ll,int rr,int cur,LL v)
{if(l<=ll&&r>=rr){a[cur].v += v;a[cur].tag += v;return ;}pushdown(cur);int mid = (ll +rr)>>1;if(mid < r) update(l,r,mid + 1,rr,cur<<1|1,v);if(mid >= l) update(l,r,ll,mid,cur<<1,v);pushup(cur);
}LL quiry(int l,int r,int ll,int rr,int cur)
{if(l<=ll&&r>=rr){return a[cur].v;} pushdown(cur);int mid = (ll + rr) >> 1;LL t1 =INF;LL t2 = INF;if(mid < r) t1 = quiry(l,r,mid + 1,rr,cur<<1|1);if(mid >= l) t2 =  quiry(l,r,ll,mid,cur<<1);return Min(t1,t2);
}int main()
{int n;scanf("%d", &n);built(1,n,1);int m;scanf("%d", &m);while(m--){int a,b,c;char ch;scanf("%d%d%c", &a, &b, &ch);a++,b++;if(ch != ' '){if(a>b){LL t1=quiry(a,n,1,n,1);LL t2 = quiry(1,b,1,n,1);printf("%I64d\n",Min(t1,t2));}elseprintf("%I64d\n",quiry(a,b,1,n,1));}else {scanf("%d", &c);if(a>b){update(a,n,1,n,1,c);update(1,b,1,n,1,c);}else update(a,b,1,n,1,c);}}return 0;
}

这篇关于Circular RMQ的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/857417

相关文章

python circular import python循环导入问题

遇到的问题是因为模块之间存在循环导入(circular import),导致了ImportError。循环导入是指两个或多个模块相互导入对方,如模块A导入了模块B的方法,模块B又导入了模块A的方法,从而导致其中一个模块在完全初始化之前就被另一个模块尝试导入,进而引发错误。 解决循环导入问题的方法 重构代码结构: 尽量避免模块之间的直接相互导入。可以考虑将公共的部分抽象出来,放到单独的模块中。

【HDU】5436 Transmigration tree【树链剖分+dp+rmq】

题目链接:【HDU】5436 Transmigration tree #pragma comment(linker, "/STACK:16777216")#include <stdio.h>#include <string.h>#include <vector>#include <algorithm>using namespace std ;typedef long long LL ;

区间最值查寻(RMQ问题)

RMQ问题就是区间最小值问题,这是一个非常经典的题, 由他引申出来的也是不计其数最多的是给出一个区间,然后输入多组区间端点,求输入区间的最小值。 每次用循环来计算一个最小值显然不够快,怎么办呢? 实践中最常用的是Tarjan的 Sparse-Table算法,它的预处理时间是O(nlogn),但是查询只需要O(1),而且常数很小。 它的思想很简单,就是递推+二分的思想。我们先定义一个二维数组

人生第一条线段树!!!!FLY 1427: RMQ 两数之间最小值

1427: RMQ 两数之间最小值 时间限制: 2 Sec   内存限制: 128 MB 提交: 103   解决: 28 [ 提交][ 状态][ 讨论版] 题目描述 给N(1 <= N <= 250,000)个数, 和Q(0 <= Q <= 100,000)个询问, 对于每个询问求出所求两数之间(包括这两个数)的最小数. 输入 第一行: N 以下N行,

POJ 3264 RMQ--ST 算法

Balanced Lineup Time Limit: 5000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u Submit Status Description For the daily milking, Farmer John’s N cows (1 ≤ N ≤ 50,000) always line up in the

RMQ问题(士兵杀敌(三))

士兵杀敌(三) 时间限制: 2000 ms  |  内存限制: 65535 KB 难度: 5 描述 南将军统率着N个士兵,士兵分别编号为1~N,南将军经常爱拿某一段编号内杀敌数最高的人与杀敌数最低的人进行比较,计算出两个人的杀敌数差值,用这种方法一方面能鼓舞杀敌数高的人,另一方面也算是批评杀敌数低的人,起到了很好的效果。 所以,南将军经常问军师小工第i号士兵到第j号士

poj3264--Balanced Lineup(RMQ求最大最小)

Balanced Lineup Time Limit: 5000MS Memory Limit: 65536KTotal Submissions: 33665 Accepted: 15830Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000)

codeforces #52 C Circular RMQ(线段树)

题目地址:http://codeforces.com/problemset/problem/52/C 线段树区间更新水题。 代码如下: #include <iostream>#include <cstdio>#include <string>#include <cstring>#include <stdlib.h>#include <math.h>#include <ctyp

HDU 5409 CRB and Graph【dfs序+RMQ】

先用trajan缩环变成了一棵树 然后删除了一条边就将树分成了两个部分,一个是删除的那边下面的子树,一个是剩余部分。那么要查询的是两个部分中最大的点的值,和不大于它的最小的点的值。 这样一想就有点像树链剖分啊,树形DP一样求出一颗子树的某个最大值。 又想到是分离出一颗子树,那么就是想到一些dfs序可以对子树进行区间求值。 那么就想到可以预处理出dfs序列,将树的值转化为一个区间值。去掉一颗子

洛谷 P3379:最近公共祖先(LCA)← RMQ+欧拉序

【题目来源】https://www.luogu.com.cn/problem/P3379【题目描述】 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先。【输入格式】 第一行包含三个正整数 N,M,S,分别表示树的结点个数、询问的个数和树根结点的序号。 接下来 N−1 行每行包含两个正整数 x,y,表示 x 结点和 y 结点之间有一条直接连接的边(数据保证可以构成树)。 接下来 M 行每