Problem: Write a program which manipulates a sequence $A$ = {$a_0, a_1, ..., a_{n-1}$} with the following operations:

* $add(s, t, x)$ : add $x$ to $a_s, a_{s+1}, ..., a_t$.
* $find(s, t)$ : report the minimum value in $a_s, a_{s+1}, ..., a_t$.



Note that the initial values of $a_i ( i = 0, 1, ..., n-1 )$ are 0.

Constraints

* $1 ≤ n ≤ 100000$
* $1 ≤ q ≤ 100000$
* $0 ≤ s ≤ t < n$
* $-1000 ≤ x ≤ 1000$

Input


$n$ $q$
$query_1$
$query_2$
:
$query_q$


In the first line, $n$ (the number of elements in $A$) and $q$ (the number of queries) are given. Then, $i$th query $query_i$ is given in the following format:


0 $s$ $t$ $x$


or


1 $s$ $t$


The first digit represents the type of the query. '0' denotes $add(s, t, x)$ and '1' denotes $find(s, t)$.

Output

For each $find$ query, print the minimum value.

Example

Input

6 7
0 1 3 1
0 2 4 -2
1 0 5
1 0 1
0 3 5 3
1 3 4
1 0 5


Output

-2
0
1
-1

Solution (in CPP):

Solution:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
#include<map>
#include<set>
#include<string>
#include<stack>
#include<queue>
#define null NULL
using namespace std;
/** 区间表示：[p->dl,p->dr]
 *  从0开始计数，[0,n-1]
 *  线段树RSQ
 *
 */

struct Node
{
    long long dl,dr,s,delta;
    Node *pl,*pr;
};
int n,q;

void build(Node *&p,int l,int r)
{
    p=(Node *)malloc(sizeof(Node));
    p->dl=l,p->dr=r,p->s=0,p->delta=0;
    p->pl=null,p->pr=null;
    int mid=(l+r)/2;
    if(r>l)
    {
        build(p->pl,l,mid);
        build(p->pr,mid+1,r);
    }
}

void preorder(Node *p)
{
    if(p!=null)
    {
        printf("%lld %lld %lld %lld\n",p->dl,p->dr,p->s,p->delta);
        preorder(p->pl);
        preorder(p->pr);
    }
}
///在其他节点更新和查询的过程中都要向下延迟修改
void pushdown(Node *&p,int delta)
{
    p->pl->s += p->delta;
    p->pr->s += p->delta;
    p->pl->delta += p->delta;
    p->pr->delta += p->delta;
    p->delta=0;
}
///当前区间的更新只更新到某些节点，下边节点的更新需要下次延迟修改
void update(Node *&p,int l,int r,int data)
{
    ///[l,r]必然位于[p->dl,p->dr]子区间
    ///当前节点的所有数据都是正确的！！
    ///延迟修改-lazy-tag技术
    ///此处下行的是之前的数据
    if(p->delta!=0 && p->dr>p->dl)
        pushdown(p,p->delta);

    if(p->dl==l &&p->dr==r)
    {
        p->s += data;
        p->delta=data;
        return ;
    }
    int mid=(p->dl+p->dr)/2;
    if(r<=mid)
        update(p->pl,l,r,data);
    else if(l>mid)
        update(p->pr,l,r,data);
    else
        update(p->pl,l,mid,data),update(p->pr,mid+1,r,data);
    p->s=min(p->pl->s,p->pr->s);
}
///当前节点的所有数据都是正确的！！
///即使不正确，在进入到这个之前也被pushdown过了,，所以一定是正确的
long long query(Node *&p,int l,int r)
{
    ///一个查询区间最终必然被分成若干个小的区间和，最后一个定会完全和区间贴合
    if(p->delta!=0 && p->dr>p->dl)
        pushdown(p,p->delta);

    if(p->dl==l &&p->dr==r)
        return p->s;
    int mid=(p->dl+p->dr)/2;
    ///判断查询区间与当前区间的位置关系
    //全部位于左侧
    if(r<=mid)
        return query(p->pl,l,r);
    //全部位于右侧
    else if(l>mid)
        return query(p->pr,l,r);
    //两个都有
    else
        return min(query(p->pl,l,mid),query(p->pr,mid+1,r));
}

int main()
{
    int i,type,tx,ty,x;
    Node *tree=null;
    scanf("%d%d",&n,&q);
    build(tree,0,n-1);
    for(i=0;i<q;i++)
    {
        scanf("%d",&type);
        if(type==0)
        {
            scanf("%d%d%d",&tx,&ty,&x);
            update(tree,tx,ty,x);
        }else
        {
            scanf("%d%d",&tx,&ty);
            long long ans=query(tree,tx,ty);
            printf("%lld\n",ans);
        }
    }
    return 0;
}