Input file: standard input
Output file: standard output
Time limit: 1 second
Memory limit: 512 mebibytes

Every year, the ACM/ICPC team will hold many contests, some of them are training while others are school contests.

In the year of 2017, there are WOJ 641 Events 区间分块_i++ contests to be held, and at the beginning of year, we plans the time of each contest.

However, as things are changing. Some other events might affect the time of contest and our team leader wants to know some interesting things about the time of some events.

Input

The first line contains an integer WOJ 641 Events 区间分块_i++. (WOJ 641 Events 区间分块_线段树_03)

The second line contains WOJ 641 Events 区间分块_i++ integers, the WOJ 641 Events 区间分块_分块算法_05-th one of them is WOJ 641 Events 区间分块_分块_06, which is the planning time of contest WOJ 641 Events 区间分块_分块算法_05 at the beginning of this year. (WOJ 641 Events 区间分块_i++_08)

The third line contains an integer WOJ 641 Events 区间分块_最小值_09. And then WOJ 641 Events 区间分块_最小值_09 lines follows. (WOJ 641 Events 区间分块_i++_11)

Then each line contains three integers. WOJ 641 Events 区间分块_分块算法_12,WOJ 641 Events 区间分块_分块_13,WOJ 641 Events 区间分块_分块算法_14, means the time of WOJ 641 Events 区间分块_分块算法_12-th contest to WOJ 641 Events 区间分块_分块_13-th contest will be changed by WOJ 641 Events 区间分块_分块算法_14. And then you should output the earlist time of WOJ 641 Events 区间分块_分块算法_12-th contest to WOJ 641 Events 区间分块_分块_13-th contest in the history after the change of time. (WOJ 641 Events 区间分块_线段树_20,WOJ 641 Events 区间分块_分块算法_21)

Output

Output contains WOJ 641 Events 区间分块_最小值_09 lines, WOJ 641 Events 区间分块_分块算法_05-th line is the answer after WOJ 641 Events 区间分块_分块算法_05-th query.

Examples

Input 1

4
1 2 3 4
3
1 2 2
2 3 3
3 4 -10

Output 1

1
2
-6

Note

At the beginning, WOJ 641 Events 区间分块_分块_06 are WOJ 641 Events 区间分块_最小值_26. After the first change on time, WOJ 641 Events 区间分块_分块_06 becomes WOJ 641 Events 区间分块_分块算法_28, and then WOJ 641 Events 区间分块_最小值_29, and at last becomes WOJ 641 Events 区间分块_分块算法_30.

Be careful that as the times are relative times, so they can be negative.

        没错,这题就是当时死都写不出来然后又耗了很多时间的题目!罪魁祸首啊!

        当时的想法是用线段树维护当前区间最小和历史区间最小,然后只想到用一个lazytag去维护它,但是写完发现这样会WA,因为如果仅仅一个lazytag维护区间加减,无法将历史最小的信息下传,即容易被后来的lazytag覆盖。举个例子来说,如果我在[1,5]区间减一,紧接着又在[1,5]区间加一,那么这个lazytag就只会在大区间中出现过,子区间的历史最小就没有被改变过,显然这是错的。但是貌似数据比较水,据说Rank1的AK队伍就是这样水过的,赛后测了一下他们的代码也是不对的。至于线段树的正解,我就不在这篇文章里讲了,这个我赛后也是有仔细思考的。

        下面说说分块算法。当初我在讲莫队算法的时候就提到了这个分块算法,但是其实我并不知道它的神奇作用,知道碰到这一道题目。和当时莫队算法说的一样,分块算法简而言之就是把大区间分成许多一个个的小块,然后再块与块之间暴力修改,在单个块的内部也暴力修改,其实说白了也可以说是一种暴力,只不过特别巧罢了。一般来说,我们通常把长度为N的区间分成根号N块,每块的长度为根号N,这样可以取得最佳的效率。

        以本题为例,我们把十万的区间分成长度为300的许多块。对于每一个块,我维护一个当前块最小值,和当前块历史最小。对于每一个点,我也保存一个当前最小和历史最小。当有一个询问l,r,x时,找到l和r两点对应的块,暴力的下传块的lazytag上的信息,同时也暴力的对 l到其所在块的右端点 和 r所在块的左端点到r 的区间修改。至于中间的整个部分的块,我们就如线段树般整体的修改,打上lazytag。

       对于lazytag,这里要用两个lazytag(线段树解法的正解也要用两个),一个表示区间变化量,另一个表示历史最小的变化量,即保留至上次更新前最小的一个变化量x。然后在标记下传的时候,用自上次更新以来的单点数值 加上历史最小变化量 之后的值去更新单点历史最小值,再用这些单点历史最小值更新 块 历史最小值。可能说的不清楚orz.....等等在代码中说吧。

        最后再总结一下分块算法吧。这个方法就是分成块去暴力,然后复杂度很容计算,一般为O(N^1.5),也即对于10W级的数据可以用这种算法。而他的优势在于相对于那些数据结构更加的好写不容易出错。具体代码如下:

#include<bits/stdc++.h>
#define blocks 300
using namespace std;

long long cur[500],his[500],lazy1[500],lazy2[500]; //cur:块当前值,his:块历史最小值,lazy1:块变化量,lazy2:块历史最小变化量
long long a[101000],m[101000]; //a:单点数值,m:单点历史最小数值
int n,q;

long long inblocks(int num,int l,int r,long long delta) //处理单个块
{
for(int i=num*blocks;i<min(n,(num+1)*blocks);i++) //对每个块中的单点暴力下传lazytag
{
m[i]=min(m[i],a[i]+lazy2[num]); //用自上次更新以来的单点数值 加上历史最小变化量 之后的值去更新单点历史最小值
a[i]+=lazy1[num];
}
lazy1[num]=lazy2[num]=0;
for(int i=num*blocks+l;i<=num*blocks+r;i++)
{
a[i]+=delta; m[i]=min(m[i],a[i]); //区间暴力修改
}
cur[num]=a[num*blocks];
for(int i=num*blocks;i<min(n,(num+1)*blocks);i++) //维护块中当前最小和历史最小值
{
cur[num]=min(cur[num],a[i]);
his[num]=min(his[num],m[i]);
}
long long ans=m[num*blocks+r];
for(int i=num*blocks+l;i<num*blocks+r;i++) //返回区间最小值
ans=min(ans,m[i]);
return ans;
}

long long wholeblocks(int num,long long delta)
{
lazy1[num]+=delta;
lazy2[num]=min(lazy2[num],lazy1[num]); //更新最小历史变化量
cur[num]+=delta;
his[num]=min(his[num],cur[num]);
return his[num]; //返回块最小
}

int main()
{
scanf("%d",&n);
for(int i=0;i<=n/blocks;i++) his[i]=1e12;
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]); m[i]=a[i];
cur[i/blocks]=his[i/blocks]=min(a[i],his[i/blocks]);
}
scanf("%d",&q);
while (q--)
{
long long l,r,x;
scanf("%lld%lld%lld",&l,&r,&x);
if (l/blocks==r/blocks) //区间在同一个块中则直接暴力求解
printf("%lld\n",inblocks(l/blocks,l%blocks,r%blocks,x));
else //否则分段处理
{
long long ans;
ans=min(inblocks(l/blocks,l%blocks,blocks-1,x),inblocks(r/blocks,0,r%blocks,x)); //修改两个"半"区间
for(int i=l/blocks+1;i<r/blocks;i++)
ans=min(ans,wholeblocks(i,x)); //暴力修改块并返回块历史最小
printf("%lld\n",ans);
}
}
}