很板的题,我建了三棵树,分别维护区间和最大值最小值,当然更简洁的写法是结构体一次挂三个属性。不过也没差其实。
要注意的是,查询时初始化最小值最大值要用llinf,之前定义的inf是不够的,详见我的宏定义。
话说这两个还是之前偷看zh的cf上的代码学来的(斜眼笑)……
#include<bits/stdc++.h>
#define maxn 10000005
#define maxm 200005
#define FOR(a, b, c) for(int a=b; a<=c; a++)
#define hrdg 1000000007
#define inf 2147483647
#define llinf 9223372036854775807
#define ll long long
#define pi acos(-1.0)
#define ls p<<1
#define rs p<<1|1
using namespace std;
ll n, m, a[maxn], tr[maxn<<2], tr2[maxn<<2], tr3[maxn<<2], tag[maxn<<2];
ll type, l, r, k;
//快读
inline ll read()
{
char c=getchar();long long x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void pushup(ll p)
{
tr[p] = tr[ls] + tr[rs];
tr2[p] = max(tr2[ls], tr2[rs]);
tr3[p] = min(tr3[ls], tr3[rs]);
}
void build(ll p, ll l, ll r)
{
tag[p] = 0;
if(l==r)
return;
ll mid = (l+r)>>1;
build(ls, l, mid);
build(rs, mid+1, r);
pushup(p);
}
void load(ll p, ll l, ll r, ll k)
{
tag[p] += k;
tr[p] += k*(r-l+1);
tr2[p] += k;
tr3[p] += k;
}
void pushdown(ll p, ll l, ll r)
{
ll mid = (l+r)>>1;
load(ls, l, mid, tag[p]);
load(rs, mid+1, r, tag[p]);
tag[p] = 0;
}
void update(ll nl, ll nr, ll l, ll r, ll p, ll k)
{
if(nl <= l && nr >= r)
{
load(p, l, r, k);
return;
}
pushdown(p, l, r);
ll mid = (l+r)>>1;
if(nl <= mid)
update(nl, nr, l, mid, ls, k);
if(nr >= mid+1)
update(nl, nr, mid+1, r, rs, k);
pushup(p);
}
ll query1(ll nl, ll nr, ll l, ll r, ll p)
{
ll ret = 0;
if(nl <= l && nr>= r) return tr[p];
ll mid = (l+r)>>1;
pushdown(p, l, r);
if(nl <= mid)
ret += query1(nl, nr, l, mid, ls);
if(nr >= mid+1)
ret += query1(nl, nr, mid+1, r, rs);
return ret;
}
ll query2(ll nl, ll nr, ll l, ll r, ll p)
{
ll ret = -llinf/10;
if(nl <= l && nr>= r) return tr2[p];
ll mid = (l+r)>>1;
pushdown(p, l, r);
if(nl <= mid)
ret = max(ret, query2(nl, nr, l, mid, ls));
if(nr >= mid+1)
ret = max(ret, query2(nl, nr, mid+1, r, rs));
return ret;
}
ll query3(ll nl, ll nr, ll l, ll r, ll p)
{
ll ret = llinf/10;
if(nl <= l && nr >= r) return tr3[p];
ll mid = (l+r)>>1;
pushdown(p, l, r);
if(nl <= mid)
ret = min(ret, query3(nl, nr, l, mid, ls));
if(nr >= mid+1)
ret = min(ret, query3(nl, nr, mid+1, r, rs));
return ret;
}
int main()
{
n = read();
m = read();
build(1, 1, n);
FOR(i, 1, m)
{
type = read();
l = read();
r = read();
if(type == 1)
{
k = read();
update(l, r, 1, n, 1, k);
}
if(type == 2)
{
ll ans = query1(l, r, 1, n, 1);
printf("%lld\n", ans);
}
if(type == 3)
{
ll ans = query2(l, r, 1, n, 1) - query3(l, r, 1, n, 1);
printf("%lld\n", ans);
}
}
return 0;
}