【题目大意】
给出环形数列a_0,a_1,...,a_n-1。它有两种操作:
inc(lf,rg,v)这个操作使[lf,rg]区间内的每一个值增加v;
rmq(lf,rg)这个操作返回[lf,rg]区间内的最小值。
假设区间是环形的,所以当n=5,lf=3,rg=1时,表示的序列编号为:3,4,0,1。
请编写程序执行这一系列操作。
【输入】
第一行有一个整数n。
第二行为数列的初始状态a_0,a_1,...,a_n-1,a_i是整数。
第三行有一个整数m,表示操作次数。
接下来m行每行为一个操作。如果该行有两个整数lf,rg表示rmq操作,如果该行有三个整数lf,rg,v表示inc操作。
【输出】
对于每个rmq操作输出一行答案。
【样例】
输入
4
1 2 3 4
4
3 0
3 0 -1
0 1
2 1
输出
1
0
0
【数据规模】
1<=n<=200000
-10^6<=a_i,v<=10^6
0<=m<=200000
0<=lf,rg<=n-1
【分析】
很明显这是一个在线查询区间、修改区间的问题,可以用线段树解决。由于数列是环形的,在处理操作时要判断如果lf大于rg就拆分成[lf,n-1]和[0,rg]两个区间。输入的时候可以通过sscanf来判断读入的个数。
思路很明显:直接线段树区间修改,并且用线段树查询RMQ,第一次写不带结构体的线段树,这样写起来确实很方便,不过出好多错误,最后对照着别人的代码写。。。。。。。这样也WA了4、5次,乱改了一通过了。。T_T
以后就慢慢使用这样写线段树吧。。挺好用的。。
/****************************** * author :crazy_石头 * data structure: 线段树 * created time:2013/11/4 19:53 * Pro:CF 52C-Circular RMQ-线段树 * Judge Status:Accepted * Memory:9400K * Time:468MS *******************************/ #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; #define rep(i,h,n) for(int i=(h);i<=(n);i++) #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define ll __int64 const int maxn=200000+5; int n,m,color[maxn<<2],minn[maxn<<2],a[maxn<<2]; inline int min(int a,int b) { return a<b?a:b; } inline void pushup(int rt) { minn[rt]=min(minn[rt<<1],minn[rt<<1|1]); } inline void pushdown(int rt) { if(color[rt]) { color[rt<<1]+=color[rt]; color[rt<<1|1]+=color[rt]; minn[rt<<1]+=color[rt]; minn[rt<<1|1]+=color[rt]; color[rt]=0; } } inline void build(int l,int r,int rt) { color[rt]=0; if(l==r) { minn[rt]=a[l]; return ; } int mid=(l+r)>>1; build(lson); build(rson); pushup(rt); } inline void update(int l,int r,int rt,int L,int R,int value) { if(L<=l&&r<=R) { color[rt]+=value; minn[rt]+=value; return ; } int mid=(l+r)>>1; pushdown(rt); if(L<=mid) update(lson,L,R,value); if(R>mid) update(rson,L,R,value); pushup(rt); } inline int query(int l,int r,int rt,int L,int R) { if(L<=l&&r<=R) { return minn[rt]; } pushdown(rt); int res=1<<30; int mid=(l+r)>>1; if(L<=mid) res=query(lson,L,R); if(R>mid) res=min(res,query(rson,L,R)); return res; } int main() { int i,j,n,l,r,w; char str[300]; while(scanf("%d",&n)!=EOF) { rep(i,0,n-1) scanf("%d",&a[i]); build(0,n-1,1); scanf("%d",&m); getchar(); rep(i,1,m) { gets(str); if(sscanf(str,"%d%d%d",&l,&r,&w)==2) { if(l>r) { int ret=min(query(0,n-1,1,0,r),query(0,n-1,1,l,n)); printf("%d\n",ret); } else printf("%d\n",query(0,n-1,1,l,r)); } else if(l>r) { update(0,n-1,1,0,r,w); update(0,n-1,1,l,n,w); } else update(0,n-1,1,l,r,w); } } return 0; } |
* This source code was highlighted by YcdoiT. ( style: Codeblocks )