Gorgeous Sequence (Segment Tree)

Keywords: PHP less

Title link: http://acm.hdu.edu.cn/showproblem.php?pid=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

Analysis:
tle to wa has tle and wa.Finally ac.
55555555
I don't know how many times an int was exploded during the operation.When I was about to archive this question, I suddenly saw that the Big Guy program was multiplied by 1 LL.Successfully changed, seconds passed.There were tears from the chicken.

Reference Blog: https://blog.csdn.net/baidu_36797646/article/details/82853316
https://www.cnblogs.com/shenben/p/6641984.html
https://blog.csdn.net/nbl97/article/details/76696784
I think these three blogs are still more readable.

At the same time, suggestions: Take a look: 2016 National Team paper Jiru interval maximum operation and historical maximum problems

There are two query operations and one change value operation for this topic.We consider how segment trees are used to maintain maximum values, and.
It is not difficult to maintain and maximize a sequence.The key is how to change the value.
Here, we maintain the maximum, the second largest, and the number of maximum values at the same time.
For a t, if it is greater than the maximum of the current node, then it must return directly.
If t is greater than the next largest value, it is clear that the maximum value inside this node becomes t.The sum can also be modified using the maximum number of values.
If t is less than this large value, two children will be recursed.

The idea is simple, there is still a lot of code, and bug s can't be found.There were tears from the chicken.

#include"stdio.h"
#include"string.h"
#include"algorithm"
using namespace std;
typedef long long ll;
const int N = 1000010;

ll sum[N << 2];
int max_val[N << 2],seg_val[N << 2],num[N << 2];
int T,a[N],n,m;

void Tap_down(int id,int rmax)
{
    if(max_val[id] <= rmax) return ;
    //Note here that I started writing rmax and max_val[id] backwards. Good food!
    sum[id] = sum[id] - (max_val[id] - rmax) * (ll)num[id];
    max_val[id] = rmax;
}
void Push_down(int id)
{
   Tap_down(id << 1,max_val[id]);
   Tap_down(id << 1 | 1,max_val[id]);
}

void Push_up(int id)
{
    max_val[id] = max(max_val[id << 1],max_val[id << 1 | 1]);
    sum[id] = sum[id << 1] + sum[id << 1 | 1];
    if(max_val[id << 1] == max_val[id << 1 | 1])
    {
        seg_val[id] = max(seg_val[id << 1],seg_val[id << 1 | 1]);
        num[id] = num[id << 1] + num[id << 1 | 1]; return ;
    }
    if(max_val[id] == max_val[id << 1])
    {
        seg_val[id] = max(seg_val[id << 1],max_val[id << 1 | 1]); num[id] = num[id << 1]; return ;
    }
    seg_val[id] = max(seg_val[id << 1 | 1],max_val[id << 1]); num[id] = num[id << 1 | 1];
}

void Build_Tree(int id,int l,int r)
{
    max_val[id] = -1; seg_val[id] = -1;
    num[id] = 0; sum[id] = 0;
    if(l == r)
    {
        max_val[id] = a[l]; sum[id] = a[l]; num[id] = 1;
        return ;
    }
    int mid = (l + r) >> 1;
    Build_Tree(id << 1,l,mid);Build_Tree(id << 1 | 1,mid + 1,r);
    Push_up(id);
}

void Update(int id,int L,int R,int l,int r,int v)
{
    if(v >= max_val[id]) return ;
    if(l <= L && r >= R && seg_val[id] < v)
    {
        sum[id] = sum[id] - (max_val[id] - v) * (ll)num[id];
        max_val[id] = v;
        return ;
    }
    Push_down(id);
    int mid = (L + R) >> 1;
    if(l <= mid) Update(id << 1,L,mid,l,r,v);
    if(r > mid) Update(id << 1 | 1,mid + 1,R,l,r,v);
    Push_up(id);
}

ll Query_sum(int id,int L,int R,int l,int r)
{
    if(l <= L && r >= R) return sum[id];
    Push_down(id);
    int mid = (L + R) >> 1;
    ll ans = 0;
    if(l <= mid) ans += Query_sum(id << 1,L,mid,l,r);
    if(r > mid) ans += Query_sum(id << 1 | 1,mid + 1,R,l,r);
    return ans;
}

int Query_max(int id,int L,int R,int l,int r)
{
    if(l <= L && r >= R) return max_val[id];
    int mid = (L + R) >> 1; Push_down(id);
    int ans = 0;
    if(l <= mid) ans = max(ans,Query_max(id << 1,L,mid,l,r));
    if(r > mid) ans = max(ans,Query_max(id << 1 | 1,mid + 1,R,l,r));
    return ans;
}

void init()
{
    for(int i = 0; i <= n << 2; i ++)
        {
            sum[i] = num[i] = 0;
            max_val[i] = -1; seg_val[i] = -1;
        }
}

int main()
{
    scanf("%d",&T);
    while(T --)
    {
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; i ++)
            scanf("%d",&a[i]);
        //init();
        Build_Tree(1,1,n);
        while(m --)
        {
            int op,x,y; scanf("%d%d%d",&op,&x,&y);
            if(op == 1)
              printf("%d\n",Query_max(1,1,n,x,y));
            if(op == 2)
              printf("%lld\n",Query_sum(1,1,n,x,y));
            if(op == 0)
            {
                int t; scanf("%d",&t);
                Update(1,1,n,x,y,t);
            }
        }
    }
}

Posted by mmitdnn on Sun, 11 Aug 2019 19:59:54 -0700