ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[解题记录] P1253 [yLOI2018] 扶苏的问题

2022-01-22 19:00:16  阅读:140  来源: 互联网

标签:lazy P1253 rs int max yLOI2018 tree 扶苏 add


P1253 [yLOI2018] 扶苏的问题

题意简述

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

解题思路

就是维护一个最大值就行了

如果是操作 \(1\) ,就把 lazy 改成 \(x\),并将 add 清零

如果是操作 \(2\) ,就。。。直接加

主要是这个

void pushdown(int p){
    if(tree[p].lazy!=-INF){
	tree[ls].lazy=tree[rs].lazy=tree[p].lazy;
	tree[ls].max=tree[rs].max=tree[p].lazy;
	tree[ls].add=tree[rs].add=0;
	tree[p].lazy=-INF;
    }
    else if(tree[p].add){
	tree[ls].add+=tree[p].add;
	tree[rs].add+=tree[p].add;
	tree[ls].max+=tree[p].add;
	tree[rs].max+=tree[p].add;
	tree[p].add=0;
    }
}

我们可以定义顺序为先赋值再增加

因为在修改的时候有这么一句话

   if(x<=l&&y>=r){
	tree[p].max=k;
	tree[p].lazy=k;
	tree[p].add=0;
	return;
    }

它保证了加法一定是在修改之后的


\(Code\)

#include <bits/stdc++.h>
#define ls p<<1
#define rs p<<1|1
#define int long long
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return x*f;
}
const int N=1e6+10;
const int INF=1e16;
struct node{
    int max;
    int add;
    int lazy;
}tree[N*16];
int n,m,a[N];
void pushup(int p){
    tree[p].max=max(tree[ls].max,tree[rs].max);
    return;
}
void pushdown(int p){
    if(tree[p].lazy!=-INF){
	tree[ls].lazy=tree[rs].lazy=tree[p].lazy;
	tree[ls].max=tree[rs].max=tree[p].lazy;
	tree[ls].add=tree[rs].add=0;
	tree[p].lazy=-INF;
    }
    if(tree[p].add){
	tree[ls].add+=tree[p].add;
	tree[rs].add+=tree[p].add;
	tree[ls].max+=tree[p].add;
	tree[rs].max+=tree[p].add;
	tree[p].add=0;
    }
}
void build(int p,int l,int r){
    tree[p].lazy=-INF;
    if(l==r){tree[p].max=a[l];return;}
    int mid=(l+r)>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(p);
}
void upd1(int p,int l,int r,int x,int y,int k){
    if(x<=l&&y>=r){
	tree[p].max=k;
	tree[p].lazy=k;
	tree[p].add=0;
	return;
    }
    pushdown(p);
    int mid=(l+r)>>1;
    if(x<=mid) upd1(ls,l,mid,x,y,k);
    if(y>mid) upd1(rs,mid+1,r,x,y,k);
    pushup(p);
}
void upd2(int p,int l,int r,int x,int y,int k){
    if(x<=l&&y>=r){
	tree[p].max+=k;
	tree[p].add+=k;
	return;
    }
    pushdown(p);
    int mid=(l+r)>>1;
    if(x<=mid) upd2(ls,l,mid,x,y,k);
    if(y>mid) upd2(rs,mid+1,r,x,y,k);
    pushup(p);
}
int query(int p,int l,int r,int x,int y){
    int res=-INF;
    if(x<=l&&y>=r){
	res=max(res,tree[p].max);
	return res;
    }
    pushdown(p);
    int mid=(l+r)>>1;
    if(x<=mid) res=max(res,query(ls,l,mid,x,y));
    if(y>mid) res=max(res,query(rs,mid+1,r,x,y));
    return res;
}
signed main(){
    n=read();m=read();
    for(int i=1;i<=n;++i) a[i]=read();
    build(1,1,n);
    for(int i=1;i<=m;++i){
	int op=read();
	if(op==1){
	    int l,r,x;
	    l=read();r=read();x=read();
	    upd1(1,1,n,l,r,x);
	}
	else if(op==2){
	    int l,r,x;
	    l=read();r=read();x=read();
	    upd2(1,1,n,l,r,x);
	}
	else{
	    int l,r;
	    l=read();r=read();
	    printf("%lld\n",query(1,1,n,l,r));
	}
    }
    return 0;
}


\(Experience\)

多种操作的懒标记混合时,需要定义一个顺序

pushdown 写在

	if(x<=l&&y>=r){
    ```
    ```
    ```
	return;
    }

前面要开 \(8\) 倍空间

标签:lazy,P1253,rs,int,max,yLOI2018,tree,扶苏,add
来源: https://www.cnblogs.com/hhhd-/p/15834781.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有