HDU 5306 吉司机线段树 解题报告

Gorgeous Sequence

Problem Description

There is a sequence a of length n. We use ai to denote the i-th element in this sequence. You should do the following three types of operations to this sequence.

0 x y t: For every x≤i≤y, we use min(ai,t) to replace the original ai’s value.
1 x y: Print the maximum value of ai that x≤i≤y.
2 x y: Print the sum of ai that x≤i≤y.

Input

The first line of the input is a single integer T, indicating the number of testcases.
The first line contains two integers n and m denoting the length of the sequence and the number of operations.
The second line contains n separated integers a1,…,an (∀1≤i≤n,0≤ai<231).
Each of the following m lines represents one operation (1≤x≤y≤n,0≤t<231).
It is guaranteed that T=100, ∑n≤1000000, ∑m≤1000000.

Output

For every operation of type 1 or 2, print one line containing the answer to the corresponding query.

Sample Input

1
5 5
1 2 3 4 5
1 1 5
2 1 5
0 3 5 3
1 1 5
2 1 5

Sample Output

5
15
3
12

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 1000010
#define LL long long
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r

int t,n,m;
int mx[N<<2],se[N<<2],nm[N<<2];
LL sum[N<<2];

void pushup(int rt)
{
    nm[rt]=0;
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    mx[rt]=max(mx[rt<<1],mx[rt<<1|1]);
    se[rt]=max(se[rt<<1],se[rt<<1|1]);
    if(mx[rt]==mx[rt<<1]) nm[rt]+=nm[rt<<1];
    else se[rt]=max(se[rt],mx[rt<<1]);
    if(mx[rt]==mx[rt<<1|1]) nm[rt]+=nm[rt<<1|1];
    else se[rt]=max(se[rt],mx[rt<<1|1]);
}
void pushdown(int rt)
{
    if(mx[rt]<mx[rt<<1])
    {
        sum[rt<<1]-=(LL)nm[rt<<1]*(mx[rt<<1]-mx[rt]);
        mx[rt<<1]=mx[rt];
    }
    if(mx[rt]<mx[rt<<1|1])
    {
        sum[rt<<1|1]-=(LL)nm[rt<<1|1]*(mx[rt<<1|1]-mx[rt]);
        mx[rt<<1|1]=mx[rt];
    }
}
void build(int rt,int l,int r)
{
    if(l==r)
    {
        scanf("%I64d",&sum[rt]);
        mx[rt]=sum[rt];nm[rt]=1;
        se[rt]=-1;
        return;
    }
    int m=(l+r)>>1;
    build(lson);build(rson);
    pushup(rt);
}
int query_max(int rt,int l,int r,int L,int R)
{
    if(L<=l&&R>=r) return mx[rt];
    pushdown(rt);
    int m=(l+r)>>1,ret=0;
    if(L<=m) ret=max(ret,query_max(lson,L,R));
    if(R>m) ret=max(ret,query_max(rson,L,R));
    return ret;
}
LL query_sum(int rt,int l,int r,int L,int R)
{
    if(L<=l&&R>=r) return sum[rt];
    pushdown(rt);
    int m=(l+r)>>1;LL ret=0;
    if(L<=m) ret+=query_sum(lson,L,R);
    if(R>m) ret+=query_sum(rson,L,R);
    return ret;
}
void update(int rt,int l,int r,int L,int R,int val)
{
    if(val>=mx[rt]) return;
    if(L<=l&&R>=r&&val>se[rt])
    {
        sum[rt]-=(LL)nm[rt]*(mx[rt]-val);
        mx[rt]=val;
        return;
    } 
    pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m) update(lson,L,R,val);
    if(R>m) update(rson,L,R,val);
    pushup(rt);
}
int main()
{
    for(scanf("%d",&t);t;--t)
    {
        scanf("%d%d",&n,&m);
        build(1,1,n);
        while(m--)
        {
            int opt,l,r;
            scanf("%d%d%d",&opt,&l,&r);
            if(opt==0)
            {
                int val;scanf("%d",&val);
                update(1,1,n,l,r,val);
            }
            if(opt==1)
            {
                printf("%d\n",query_max(1,1,n,l,r));
            }
            if(opt==2)
            {
                printf("%I64d\n",query_sum(1,1,n,l,r));
            }
        }
    }
    return 0;
}
/*
1
5 5
1 2 3 4 5
1 1 5
2 1 5
0 3 5 3
1 1 5
2 1 5
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值