HDU 5306 Gorgeous Sequence(线段树同时处理多种数组信息)

继续补专题

题目思路

题目给出三种操作
查询区间最大值
查询区间和
给出数据v 将区间中每个点修改为min(a[i],v)
前面两个是基本的线段树操作 很好实现
但第三个就不好实现了,也是本题的难点
如果对区间内每个点做修改 时间复杂度上太大 这里要用lazy_tag的思想
还有注意数据范围 记得开ll(wa了无数次了 菜鸡落泪)

以下图片据说是16年国家集训队jls的论文 也是本题的主要思路
在这里插入图片描述在这里插入图片描述

ac代码

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 2e5+10;
const int inf = 0x1f1f1f1f;
const int mod = 2333;

ll a[maxn];
//从左往右四个数组分别记录区间和,区间最大值,区间严格次大值,区间最大值出现的次数
ll tsum[maxn<<2],tmax[maxn<<2],tse[maxn<<2],tcnt[maxn<<2];

//本题重要函数 内容有点绕 之前这里写搓了wa了挺多发 写的时候建议先理清思路归好类 不要直接一个情况一个情况的特判
void pushup(int rt)
{
    tsum[rt]=tsum[lson]+tsum[rson];
    tmax[rt]=max(tmax[lson],tmax[rson]);
    if(tmax[lson]==tmax[rson])
    {
        tse[rt]=max(tse[lson],tse[rson]);
        tcnt[rt]=tcnt[lson]+tcnt[rson];
    }else
    {
        tse[rt]=min(tmax[lson],tmax[rson]);
        tse[rt]=max(tse[rt],max(tse[lson],tse[rson]));
        if(tmax[rt]==tmax[lson])
            tcnt[rt]=tcnt[lson];
        else
            tcnt[rt]=tcnt[rson];
    }

}

//lazy_tag 不同于我之前学的直接用lazy数组记录 这里因为改变了最大值 直接进行比较 大于当前最大值的话 那么这个区间是要被修改 但还未被修改的区间
void pushtag(int rt,int x)
{
    if(x>=tmax[rt])return;
    tsum[rt]-=tcnt[rt]*(tmax[rt]-x);
    tmax[rt]=x;
}

void pushdown(int rt)
{
    pushtag(lson,tmax[rt]);
    pushtag(rson,tmax[rt]);
}

void build(int rt,int l,int r)
{
    if(l==r)//将维护的多个信息初始化
    {
       tmax[rt]=tsum[rt]=a[l];
       tse[rt]=0;
       tcnt[rt]=1;
       return;
    }
    int mid=(l+r)>>1;
    build(lson,l,mid);
    build(rson,mid+1,r);
    pushup(rt);
}

void change(int L,int R,int l,int r,int v,int rt)
{
    if(tmax[rt]<=v)
    {
        return;
    }
    if(tse[rt]<v&&L<=l&&r<=R)
    {
        pushtag(rt,v);
        return;
    }
    pushdown(rt);
    int mid=(l+r)>>1;
    if(L<=mid)
        change(L,R,l,mid,v,lson);
    if(R>mid)
        change(L,R,mid+1,r,v,rson);
    pushup(rt);
}

ll query_sum(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        return tsum[rt];
    }
    int mid=(l+r)>>1;
    pushdown(rt);
    ll res=0;
    if(L<=mid)
        res+=query_sum(L,R,l,mid,lson);
    if(R>mid)
        res+=query_sum(L,R,mid+1,r,rson);
    return res;
}

ll query_max(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        return tmax[rt];
    }
    int mid=(l+r)>>1;
    pushdown(rt);
    ll res=0;
    if(L<=mid)
        res=max(res,query_max(L,R,l,mid,lson));
    if(R>mid)
        res=max(res,query_max(L,R,mid+1,r,rson));
    return res;
}

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,q;
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
        }
        build(1,1,n);
        while(q--)
        {
            int tp;
            scanf("%d",&tp);
            if(tp==0)
            {
                int l,r,v;
                scanf("%d%d%d",&l,&r,&v);
                change(l,r,1,n,v,1);
            }
            if(tp==1)
            {
                int l,r;
                scanf("%d%d",&l,&r);
                ll ans=query_max(l,r,1,n,1);
                printf("%lld\n",ans);
            }
            if(tp==2)
            {
                int l,r;
                scanf("%d%d",&l,&r);
                ll ans=query_sum(l,r,1,n,1);
                printf("%lld\n",ans);
            }
        }
    }

}

猜你喜欢

转载自blog.csdn.net/daydreamer23333/article/details/107303924