过六个点,还有四个点,大佬们救救我,孩子改麻了,改了好久个小时

P1253 扶苏的问题

JunBuJian @ 2022-07-04 11:14:14

#include<iostream>
#include<cmath>

using namespace std;

typedef long long LL;
const int N = 1e6 + 5;
LL M = -1e16;
int n,m;
int w[N];

struct Node
{
    int l,r;
    LL max;
    LL t1;//区间变量
    LL t2;//增加变量
}tr[N * 4];

void pushup(int u)
{
    tr[u].max = max(tr[u << 1].max,tr[u << 1 | 1].max);
}

void pushdown(int u)//消除标记
{
    auto &root = tr[u],&left = tr[u << 1],&right = tr[u << 1 | 1];

    if(root.t1 != M)
    {
    left.max = right.max = root.t1; 
    left.t1 = right.t1 = root.t1;
    left.t2 = right.t2 = 0;
    root.t1 = M;
    }

    if(root.t2) 
    {  
    left.max += root.t2;
    right.max += root.t2; 
    left.t2 += root.t2;
    right.t2 += root.t2;
    root.t2 = 0; 
    }
}

void build(int u,int l,int r)
{
    if(l == r) tr[u] = {l,r,w[r],M,0};
    else {
        tr[u] = {l,r,0,M,0};
        int mid = l + r >> 1;
        build(u << 1,l,mid);
        build(u << 1 | 1,mid + 1,r);
        pushup(u);
    }
}

void modify2(int u,int l,int r,int d)
{
    if(tr[u].l >= l && tr[u].r <= r)
    {
    tr[u].t2 += d;//标记
    tr[u].max += d;
    }
    else // 分裂
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if(l <= mid) modify2(u << 1,l,r,d);
        if(r > mid) modify2(u << 1 | 1,l,r,d);
        pushup(u);
    }
}

void modify1(int u,int l,int r,int d)
{
    if(tr[u].l >= l && tr[u].r <= r)
    {
    tr[u].t1 = d;//标记
    tr[u].max = d;
    }
    else // 分裂
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if(l <= mid) modify1(u << 1,l,r,d);
        if(r > mid) modify1(u << 1 | 1,l,r,d);
        pushup(u);
    }
}

LL query(int u,int l,int r)
{
    if(tr[u].l >= l && tr[u].r <= r) return tr[u].max;
    pushdown(u);

    int mid = tr[u].l + tr[u].r >> 1;
    LL  res = M;
    if(l <= mid) res = query(u << 1,l,r);
    if(r > mid) res = max(res,query(u << 1 | 1,l,r));

    return res;
}

int main()
{
    scanf("%d %d",&n,&m);

    for(int i = 1;i <= n;i ++) cin >> w[i];
    build(1,1,n);

    int op;
    int l,r,x;

/*op=1,三个整数 l, r, x [l,r] 内的每个数都修改为 x
若op=2,三个整数 l, r, x [l,r] 内的每个数都加上 x
若op=3,两个整数 l, r 表示查询区间 [l, r][l,r] 内的最大值。

*/
    while(m --)
    {
        scanf("%d",&op);
        if(op == 1){
            scanf("%d%d%d",&l,&r,&x);
            modify1(1,l,r,x);
        }
        else if(op == 2){
            scanf("%d%d%d",&l,&r,&x);
            modify2(1,l,r,x);
        }
        else {
            scanf("%d%d",&l,&r);
            printf("%lld\n",query(1,l,r));
        }
    }
    return 0;
}

by Ruiqun2009 @ 2022-07-04 11:30:17

这道题odt可以做到80分?


by JunBuJian @ 2022-07-04 12:09:49

@Ruiqun2009 odt啥意思。。。


by Ruiqun2009 @ 2022-07-04 12:11:19

@JunBuJian 详情见CF896C。


|