题目地址
题目描述
You are given circular array a_{0},a_{1},…,a_{n-1}a
0
,a
1
,…,a
n−1
. There are two types of operations with it:
inc(lf,rg,v)inc(lf,rg,v) — this operation increases each element on the segment [lf,rg][lf,rg] (inclusively) by vv ;
rmq(lf,rg)rmq(lf,rg) — this operation returns minimal value on the segment [lf,rg][lf,rg] (inclusively).
Assume segments to be circular, so if n=5n=5 and lf=3,rg=1lf=3,rg=1 , it means the index sequence: 3,4,0,13,4,0,1 .
Write program to process given sequence of operations.
输入格式
The first line contains integer nn ( 1<=n<=2000001<=n<=200000 ). The next line contains initial state of the array: a_{0},a_{1},…,a_{n-1}a
0
,a
1
,…,a
n−1
( -10{6}<=a_{i}<=10{6}−10
6
<=a
i
<=10
6
), a_{i}a
i
are integer. The third line contains integer mm ( 0<=m<=2000000<=m<=200000 ), mm — the number of operartons. Next mm lines contain one operation each. If line contains two integer lf,rglf,rg ( 0<=lf,rg<=n-10<=lf,rg<=n−1 ) it means rmqrmq operation, it contains three integers lf,rg,vlf,rg,v ( 0<=lf,rg<=n-1;-10{6}<=v<=10{6}0<=lf,rg<=n−1;−10
6
<=v<=10
6
) — incinc operation.
输出格式
For each rmqrmq 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).
题意翻译
【题目大意】
给定一个环形数列 a_0,a_1,\dots,a_{n-1}a
0
,a
1
,…,a
n−1
。
现在有 22 种操作:
\operatorname{inc}(lf,rg,v)inc(lf,rg,v):将区间 [lf,rg][lf,rg] 中的每个数增加 vv。
\operatorname{rmq}(lf,rg)rmq(lf,rg):求出区间 [lf,rg][lf,rg] 中的最小值。
因为数列是环形的,所以当 n=5n=5,lf=3lf=3,rg=1rg=1 时,表示的区间下标为 3,4,0,13,4,0,1。
Translated by 小恐。
【输入】
第一行有一个整数 nn。
第二行为数列的初始状态 a_0,a_1,\dots,a_{n-1}a
0
,a
1
,…,a
n−1
,a_ia
i
是整数。
第三行有一个整数 mm,表示操作次数。
接下来m行每行为一个操作。如果该行有两个整数 lflf,rgrg 表示 \operatorname{rmq}rmq 操作,如果该行有三个整数 lflf,rgrg,vv 表示 \operatorname{inc}inc 操作。
【输出】
对于每个 \operatorname{rmq}rmq 操作输出一行答案。
求区间最小值,这道题加深了我对线段树的理解。
同时每一行可以用快速读入判断空格个数来判断输入个数。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const long long inf=0x3f3f3f3f;
int a[200010],space;
struct node{
int l,r,len,lazy,val,mi;
}tree[800010];//树状数组的大小要是数据量的4倍
int read(){
int res=0,f=1;
char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-1;c=getchar();}
while (isdigit(c)) res=res*10+c-48,c=getchar();
if (c==' ') ++space; //空格的个数
return res*f;
}
void buil(int l,int r,int root){//构造线段树
tree[root].l=l;
tree[root].r=r;
tree[root].lazy=0;
tree[root].len=r-l+1;//根据需要可添加其它元素
tree[root].mi=inf;
if(l==r){
tree[root].val=a[l];
tree[root].mi=a[l];
}
else{
int m=(l+r)/2;
buil(l,m,root*2);
buil(m+1,r,root*2+1);
tree[root].val=tree[root*2].val+tree[root*2+1].val;
tree[root].mi=min(tree[root*2].mi,tree[root*2+1].mi);
}
}
void pushdown(int root){//下推
if(tree[root].lazy){
tree[root*2].lazy+=tree[root].lazy;
tree[root*2+1].lazy+=tree[root].lazy;
tree[root*2].val+=tree[root].lazy*tree[root*2].len; //根据需要变更,
tree[root*2+1].val+=tree[root].lazy*tree[root*2+1].len; //是累加+=还是赋值=
tree[root*2].mi+=tree[root].lazy;
tree[root*2+1].mi+=tree[root].lazy;
tree[root].lazy=0;
}
}
void updata(int l,int r,int root,int x){//区间更新
if(l<=tree[root].l&&tree[root].r<=r){
tree[root].val+=x*tree[root].len;//根据需要变更,是累加+=还是赋值=
tree[root].lazy+=x;
tree[root].mi+=x;
return;
}
if(r<tree[root].l||tree[root].r<l) return;
pushdown(root);
updata(l,r,root*2,x);
updata(l,r,root*2+1,x);
tree[root].val=tree[root*2].val+tree[root*2+1].val;
tree[root].mi=min(tree[root*2].mi,tree[root*2+1].mi);
}
int query(int l,int r,int root){//区间查询,注意返回类型
if(l<=tree[root].l&&tree[root].r<=r)return tree[root].mi;
if(r<tree[root].l||tree[root].r<l)return inf;//如果用min则return inf
pushdown(root);
return min(query(l,r,root*2),query(l,r,root*2+1));
}
signed main(){
ios::sync_with_stdio(0);
int T,n,m,x;
n=read();
for(int i=1;i<=n;i++)a[i]=read();
m=read();
buil(1,n,1);
//for(int i=1;i<=4*n;i++)cout<<tree[i].mi<<' ';cout<<endl;
while(m--){
int l,r,x;
space=0;
l=read();r=read();
l++,r++;
if(space==2){
x=read();
if(r>=l)updata(l,r,1,x);
else {
updata(l,n,1,x);
updata(1,r,1,x);
}
//for(int i=1;i<=4*n;i++)cout<<tree[i].mi<<' ';cout<<endl;
}
else{
if(r>=l)cout<<query(l,r,1)<<endl;
else {
cout<<min(query(l,n,1),query(1,r,1))<<endl;
}
}
}
return 0;
}