数据结构专题 - 解题报告 - N

很板的题,我建了三棵树,分别维护区间和最大值最小值,当然更简洁的写法是结构体一次挂三个属性。不过也没差其实。
要注意的是,查询时初始化最小值最大值要用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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值