P1253 [yLOI2018] 扶苏的问题

题面

给定一个长度为 \(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\) 的操作,输出一行一个整数表示答案。

数据规模与约定

  • 对于 \(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\)

提示

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

思路

这道题太坑了。

用线段树维护区间 \(\max\),以及区间赋值与区间加的 \(\text{lazy-tag}\)

记得在赋值的时候清空 add 标记!(这个我 \(60\) 分咕了很久)。

代码

其实我觉得提示中的信息没有一点用。

#include <bits/stdc++.h>
#define ls (i<<1)
#define rs (i<<1|1)
#define mid ((l+r)>>1)
#define int long long
using namespace std;

struct node{
	int maxv,add,cov;
	node(){
		this->cov = LLONG_MIN;
		this->add = 0;
	}
} t[4000005];
int a[1000005];
int n,q;

inline void pushup(int i){
	t[i].maxv=max(t[ls].maxv,t[rs].maxv);
}

void build(int i,int l,int r){
	if(l==r){
		t[i].maxv=a[l];
	}
	else{
		build(ls,l,mid);
		build(rs,mid+1,r);
		pushup(i);
	}
}

void pushdown(int i){
    if(t[i].cov!=LLONG_MIN){
		t[ls].maxv=t[rs].maxv=t[ls].cov=t[rs].cov=t[i].cov;
		//t[ls].cov+=t[ls].add;
		//t[rs].cov+=t[rs].add;
		t[ls].add=t[rs].add=0;
		t[i].cov=LLONG_MIN;
	}
	if(t[i].add){
		t[ls].add+=t[i].add;
		t[rs].add+=t[i].add;
		t[ls].maxv+=t[i].add;
		t[rs].maxv+=t[i].add;
		t[i].add=0;
	}
}

void add(int ql,int qr,int v,int i,int l,int r){
	if(ql<=l&&r<=qr){
		t[i].maxv+=v;
		t[i].add+=v;
		return;
	}
	pushdown(i);
	if(ql<=mid){
		add(ql,qr,v,ls,l,mid);
	}
	if(mid<qr){
		add(ql,qr,v,rs,mid+1,r);
	}
	pushup(i);
}

void cover(int ql,int qr,int v,int i,int l,int r){
	if(ql<=l&&r<=qr){
		t[i].maxv=v;
		t[i].cov=v;
		t[i].add=0;
		return;
	}
	pushdown(i);
	if(ql<=mid){
		cover(ql,qr,v,ls,l,mid);
	}
	if(mid<qr){
		cover(ql,qr,v,rs,mid+1,r);
	}
	pushup(i);
}

int query(int ql,int qr,int i,int l,int r){
	if(ql<=l&&r<=qr){
		return t[i].maxv;
	}
	pushdown(i);
	int result=LLONG_MIN;
	if(ql<=mid){
		result=max(result,query(ql,qr,ls,l,mid));
	}
	if(mid<qr){
		result=max(result,query(ql,qr,rs,mid+1,r));
	}
	return result;
}

signed main(){
	cin>>n>>q;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	build(1,1,n);
	while(q--){
		int op,l,r,x;
		cin>>op;
		if(op==2){
			cin>>l>>r>>x;
			add(l,r,x,1,1,n);
		}
		if(op==1){
			cin>>l>>r>>x;
			cover(l,r,x,1,1,n);
		}
		if(op==3){
			cin>>l>>r;
			cout<<query(l,r,1,1,n)<<endl;
		}
	}
	return 0;
}

Record

posted @ 2022-04-05 10:27  蒟蒻xiezheyuan  阅读(95)  评论(0编辑  收藏  举报