【洛谷 P1253】扶苏的问题

今天还是抽了点时间写题

P1253 扶苏的问题

题目描述

给定一个长度为 \(n\) 的序列 \(a\),要求支持如下三个操作:

  1. 给定区间 \([l, r]\),将区间内每个数都修改为 \(x\)
  2. 给定区间 \([l, r]\),将区间内每个数都加上 \(x\)
  3. 给定区间 \([l, r]\),求区间内的最大值。

输入格式

第一行是两个整数,依次表示序列的长度 \(n\) 和操作的个数 \(q\)
第二行有 \(n\) 个整数,第 \(i\) 个整数表示序列中的第 \(i\) 个数 \(a_i\)
接下来 \(q\) 行,每行表示一个操作。每行首先有一个整数 \(op\),表示操作的类型。

  • \(op = 1\),则接下来有三个整数 \(l, r, x\),表示将区间 \([l, r]\) 内的每个数都修改为 \(x\)
  • \(op = 2\),则接下来有三个整数 \(l, r, x\),表示将区间 \([l, r]\) 内的每个数都加上 \(x\)
  • \(op = 3\),则接下来有两个整数 \(l, r\),表示查询区间 \([l, r]\) 内的最大值。

输出格式

对于每个 \(op = 3\) 的操作,输出一行一个整数表示答案。

输入输出样例 #1

输入 #1

6 6
1 1 4 5 1 4
1 1 2 6
2 3 4 2
3 1 4
3 2 3
1 1 6 -1
3 1 6

输出 #1

7
6
-1

输入输出样例 #2

输入 #2

4 4
10 4 -3 -7
1 1 3 0
2 3 4 -4
1 2 4 -9
3 1 4

输出 #2

0

说明/提示

数据规模与约定

  • 对于 \(10\%\) 的数据,\(n = q = 1\)
  • 对于 \(40\%\) 的数据,\(n, q \leq 10^3\)
  • 对于 \(50\%\) 的数据,\(0 \leq a_i, x \leq 10^4\)
  • 对于 \(60\%\) 的数据,\(op \neq 1\)
  • 对于 \(90\%\) 的数据,\(n, q \leq 10^5\)
  • 对于 \(100\%\) 的数据,\(1 \leq n, q \leq 10^6\)\(1 \leq l, r \leq n\)\(op \in \{1, 2, 3\}\)\(|a_i|, |x| \leq 10^9\)

提示

请注意大量数据读入对程序效率造成的影响。

解法&&个人感想

这题要求我们打上两个标记,第一个是覆盖标记,第二个是加法标记,这很容易看出来
然后,细致的pushdown操作,需要我们思考一下
因为,当某个区间被覆盖之后,由于延迟标记的关系,可能紧接着又有加法操作出现,此时,在pushdown的时候,我们就有必要慎重考虑一下要怎么操作了,在这道题里,确实需要深思熟虑,我也调了很久,就是因为上面说的,所以子树们必须继承根节点的两个懒标记,这就是精髓所在
直接放代码吧,我觉得能想出来的,多调调就好了,不想多解释

#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define lowbit(x) (x&(-x))
#define maxn 1000005
using namespace std;
const ll INF=1e18+5;
struct SegmentTree{
    ll l,r,fz,add,ma;
    bool iffz;
}tree[4*maxn];
ll ma[maxn];
ll n,m,op,x,y,k;
void build(ll x,ll l,ll r){
    tree[x].l=l;tree[x].r=r;
    if(tree[x].l==tree[x].r){
        tree[x].ma=ma[l];
        return ;
    }
    ll mid=(tree[x].l+tree[x].r)/2;
    build(x*2,l,mid);
    build(x*2+1,mid+1,r);
    tree[x].ma=max(tree[x*2].ma,tree[x*2+1].ma);
    return ;
}
void pushdown(ll x){
    if(tree[x].iffz){
        tree[x*2].iffz=true;
        tree[x*2+1].iffz=true;
        tree[x*2].fz=tree[x].fz;
        tree[x*2+1].fz=tree[x].fz;
        tree[x*2].ma=tree[x].fz+tree[x].add;
        tree[x*2+1].ma=tree[x].fz+tree[x].add;
        tree[x*2].add=tree[x].add;tree[x*2+1].add=tree[x].add;
        tree[x].add=0;
        tree[x].fz=0;
        tree[x].iffz=false;
        return ;
    }
    else if(tree[x].add){
        tree[x*2].add+=tree[x].add;
        tree[x*2+1].add+=tree[x].add;
        tree[x*2].ma+=tree[x].add;
        tree[x*2+1].ma+=tree[x].add;
        tree[x].add=0;
        return ;
    }
    return ;
}
void change_1(ll x,ll l,ll r,ll k){
    if(l<=tree[x].l&&tree[x].r<=r){
        tree[x].add=0;
        tree[x].iffz=true;
        tree[x].fz=k;
        tree[x].ma=k;
        return ;
    }
    pushdown(x);
    ll mid=(tree[x].l+tree[x].r)/2;
    if(l<=mid) change_1(x*2,l,r,k);
    if(r>mid) change_1(x*2+1,l,r,k);
    tree[x].ma=max(tree[x*2].ma,tree[x*2+1].ma);
    return ;
}
void change_2(ll x,ll l,ll r,ll k){
    if(l<=tree[x].l&&tree[x].r<=r){
        tree[x].add+=k;
        tree[x].ma+=k;
        return ;
    }
    pushdown(x);
    ll mid=(tree[x].l+tree[x].r)/2;
    if(l<=mid) change_2(x*2,l,r,k);
    if(r>mid) change_2(x*2+1,l,r,k);
    tree[x].ma=max(tree[x*2].ma,tree[x*2+1].ma);
    return ;
}
ll query(ll x,ll l,ll r){
    if(l<=tree[x].l&&tree[x].r<=r) return tree[x].ma;
    ll mid=(tree[x].l+tree[x].r)/2;
    pushdown(x);
    ll ans=-INF;
    if(l<=mid) ans=max(ans,query(x*2,l,r));
    if(r>mid) ans=max(ans,query(x*2+1,l,r));
    return ans;
}
int main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld",&ma[i]);
    }
    for(int i=1;i<=4*n;i++){
        tree[i].ma=-INF;
        tree[i].iffz=false;
    }
    build(1,1,n);
    for(int i=1;i<=m;i++){
        scanf("%lld",&op);
        if(op==1){
            scanf("%lld%lld%lld",&x,&y,&k);
            change_1(1,x,y,k);
        }
        else if(op==2){
            scanf("%lld%lld%lld",&x,&y,&k);
            change_2(1,x,y,k);
        }
        else{
            scanf("%lld%lld",&x,&y);
            ll ans=query(1,x,y);
            printf("%lld\n",ans);
        }
    }
    system("pause");
    return  0;    
}

后半学期,也请各位继续关注:
《我的青春线代物语果然有问题》
《高数女主养成计划》
《程设の旅》
《青春猪头少年不会梦到多智能体吃豆人》
《某Linux的开源软件》
《Charlotte太空探索》
还有——

《我的算法竞赛不可能这么可爱》

本期到此结束!

posted @ 2025-05-20 00:15  elainafan  阅读(42)  评论(0)    收藏  举报