25. Events (e起来编程”(武汉网络赛)) 线段树(区间修改,区间查询)

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 nn 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 nn. (0 < n \le 10^50<n105)

The second line contains nn integers, the ii-th one of them is t_iti, which is the planning time of contest ii at the beginning of this year. (0\le t_i \le 10^90ti109)

The third line contains an integer qq. And then qq lines follows. (0 < q \le 10^50<q105)

Then each line contains three integers. L_iLiR_iRiT_iTi, means the time of L_iLi-th contest to R_iRi-th contest will be changed by T_iTi. And then you should output the earlist time of L_iLi-th contest to R_iRi-th contest in the history after the change of time. (0 < L_i \le R_i \le n0<LiRin|T_i| \le 10^9Ti109)

Output

Output contains qq lines, ii-th line is the answer after ii-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, t_iti are (1,2,3,4)(1,2,3,4). After the first change on time, t_iti becomes (3,4,3,4)(3,4,3,4), and then (3,7,6,4)(3,7,6,4), and at last becomes (3,7,-4,-6)(3,7,4,6).

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


题意:n场比赛,m次操作,每场比赛有个初值,操作每次把一个区间的比赛时间修改,每次修改完需要统计这个区间历史的时间最小值。


分析:线段树问题,区间修改和区间询问。

坑点:区间问题需要一个延迟标记 cur,如果多次对一个区间进行覆盖,延迟标记cur多次累加,而下面的节点没有随之进行更新就会出现无法更新到最小值。

比如这个测试数据:

8

0 0 0 0 0 0 0 0

4

1 2 -1

1 4 -1

1 4 1

2 2 0

最后的一组 答案是-2


处理:首先是变量,每个节点需要 有一个当前最小值m、一个历史最小值 lm,一个延迟标记累加和(和指的是延迟标记累加的得到的结果) cur,一个用来保存当cur多次累加时出现的最小和 mcur,一个延迟标记累加前的m值用 变量 sm 储存。当 rt 节点 pushdown时,需要更新 rt 节点 左右孩子节点lc和rc。更新lc节点的mcur时 ,mcur就等于min(cur(lc)+mcur(rt),mcur(lc)),然后  lm(lc) =min(mcur(lc)+sm(lc),lm(lc)),接着更新lc节点的cur和m,cur(lc)+=cur(rt),m(lc)+=cur(rt);


代码;

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define mem(p,k) memset(p,k,sizeof(p));
#define rep(a,b,c) for(int a=b;a mcur[110000<<2];//第一次我用数组来保存每一个cur,然后向下更新时分析两个cur数组来更新lm,然后超内存了,后来想到这样是不需要的。 
ll minn;
int n;
ll kmin(ll a,ll b){//取最小值 
    if(a>b)return b;
    return a;
}
void pushup(int rt){//每次pushup的时候把m的初值存在sm里。 
    tree[rt].sm=tree[rt].m=kmin(tree[rt<<1|1].m,tree[rt<<1].m);
    tree[rt].lm=kmin(tree[rt].lm,tree[rt].m);
}
void build(int l,int r,int rt){
    
    if(l==r){
        scanf("%lld",&tree[rt].m);
        tree[rt].sm=tree[rt].lm=tree[rt].m;
        tree[rt].cur=0;
        tree[rt].mcur=0;
        return;
    }
    tree[rt].cur=0;
    tree[rt].mcur=0;
    tree[rt].lm=maxx;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}

void pushdown(int rt){// 更新mcur你可以想像成 B数组拼接在A数组后面,这时新的mcur就等于求新数组的以第一个数为起点的连续序列最小和。 
    
    if(tree[rt].cur||tree[rt].mcur){
        ll k=tree[rt].mcur;
        
        tree[rt<<1].mcur=kmin(tree[rt<<1].mcur,tree[rt<<1].cur+k);//tree【rt】.cur就是B数组的和,tree【rt<<1】.cur就是A数组的和, 
	                                                             //更新A数组的mcur需要比较 (B数组的mcur+A数组的cur)。 
        tree[rt<<1].cur+=tree[rt].cur;
        tree[rt<<1].lm=kmin(tree[rt<<1].mcur+tree[rt<<1].sm,tree[rt<<1].lm);//
        tree[rt<<1].m+=tree[rt].cur;
        
        tree[rt<<1|1].mcur=kmin(tree[rt<<1|1].mcur,tree[rt<<1|1].cur+k);
        tree[rt<<1|1].cur+=tree[rt].cur;
        tree[rt<<1|1].lm=kmin(tree[rt<<1|1].mcur+tree[rt<<1|1].sm,tree[rt<<1|1].lm);
        tree[rt<<1|1].m+=tree[rt].cur;

        tree[rt].cur=0;
        tree[rt].mcur=0;

    }
}
void update(int L,int R,ll c,int l,int r,int rt){

    if(L<=l&&r<=R){

        tree[rt].cur+=c;
        tree[rt].mcur=kmin(tree[rt].mcur,tree[rt].cur);
        tree[rt].m+=c;
        tree[rt].lm=kmin(tree[rt].mcur+tree[rt].sm,tree[rt].lm);

        
        return ;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,c,lson);
    if(m>1;
    pushdown(rt);
    if(L<=m)  query(L,R,lson);
    if(m>q;
       while(q--){
           int x,y;
           ll l;
           scanf("%d%d%lld",&x,&y,&l);
           minn=maxx;
           update(x,y,l,1,n,1);
           query(x,y,1,n,1);
          //for(int i=1;i<=9;i++)
          //cout<


你可能感兴趣的:(线段树)