hdu 5306 区间取min和询问区间和及最大数

题目链接

hdu 5306

题目描述

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
#include
#include
#include
#include
#include
#include
using namespace std;

const int N=1000010;
struct node{
    int mx,mx1,l,r,cnt;
    long long sum;
    void sol(int x){
        if(x>=mx) return;
        sum-=(mx-x)*1ll*cnt;
        mx=x;
    }
}t[N*4];
int a[N],op,x,y,z,n,m,T;

void push_up(int k){
    t[k].cnt=0;
    t[k].sum=t[k*2].sum+t[k*2+1].sum;
    t[k].mx=max(t[k*2].mx,t[k*2+1].mx);
    t[k].mx1=max(t[k*2].mx1,t[k*2+1].mx1);
    if(t[k*2].mx==t[k].mx) t[k].cnt+=t[k*2].cnt;
    else t[k].mx1=max(t[k].mx1,t[k*2].mx);
    if(t[k*2+1].mx==t[k].mx) t[k].cnt+=t[k*2+1].cnt;
    else t[k].mx1=max(t[k].mx1,t[k*2+1].mx);
}
void push_down(int k){
    t[k*2].sol(t[k].mx);
    t[k*2+1].sol(t[k].mx);
}
void built(int k,int l,int r){
    t[k].l=l; t[k].r=r;
    if(l==r){
        t[k].mx=t[k].sum=a[l]; 
        t[k].mx1=-1; t[k].cnt=1;
        return;
    }
    int mid=(l+r)>>1;
    built(k*2,l,mid);
    built(k*2+1,mid+1,r);
    push_up(k);
}
void modify(int k,int l,int r,int x){
    if(t[k].mx<=x) return;
    if(t[k].l==l&&t[k].r==r&&t[k].mx1return;
    }
    push_down(k);
    int mid=(t[k].l+t[k].r)>>1;
    if(l<=mid) modify(k*2,l,min(r,mid),x);
    if(r>mid) modify(k*2+1,max(l,mid+1),r,x);
    push_up(k);
}
int getmax(int k,int l,int r){
    if(t[k].l==l&&t[k].r==r) return t[k].mx;
    push_down(k);
    int mid=(t[k].l+t[k].r)>>1;
    if(r<=mid) return getmax(k*2,l,r);
    else if(l>mid) return getmax(k*2+1,l,r);
    return max(getmax(k*2,l,mid),getmax(k*2+1,mid+1,r));
}
long long getsum(int k,int l,int r){
    if(t[k].l==l&&t[k].r==r) return t[k].sum;
    push_down(k);
    int mid=(t[k].l+t[k].r)>>1;
    if(r<=mid) return getsum(k*2,l,r);
    else if(l>mid) return getsum(k*2+1,l,r);
    return getsum(k*2,l,mid)+getsum(k*2+1,mid+1,r);
}
int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",a+i);
        built(1,1,n);
        for(int i=1;i<=m;i++){
            scanf("%d%d%d",&op,&x,&y);
            if(op==0) {
                scanf("%d",&z);
                modify(1,x,y,z);
            }
            else if(op==1) printf("%d\n",getmax(1,x,y));
            else printf("%lld\n",getsum(1,x,y));
        }
    }
    return 0;
}

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