求助!
  • 板块灌水区
  • 楼主Terraria
  • 当前回复4
  • 已保存回复4
  • 发布时间2021/4/8 14:05
  • 上次更新2023/11/5 00:52:58
查看原帖
求助!
289275
Terraria楼主2021/4/8 14:05

题目大意:有 nn 个数,mm 个操作,每个操作形如 l r v 表示将区间 [l,r][l,r] 中的最大值(如果有多个则取编号最小的)减去 vv

最后输出整个数列。

数据范围:1n,m5×1041 \leq n,m \leq 5 \times 10^4

如上,线段树调假了,9090 分,一个点 MLE。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
struct node{
	int maxnum;
	int id;
}tree[2000001];
int n,m;
int a[500001];
void build(int l,int r,int p){
	if(l==r){
		tree[p].maxnum=a[l];
		tree[p].id=l;
		return;
	}
	int mid=(l+r)/2;
	build(l,mid,p*2);
	build(mid+1,r,p*2+1);
	if(tree[p*2].maxnum>=tree[p*2+1].maxnum){
		tree[p].maxnum=tree[p*2].maxnum;
		tree[p].id=tree[p*2].id;
	}
	else{
		tree[p].maxnum=tree[p*2+1].maxnum;
		tree[p].id=tree[p*2+1].id;
	}
	return;
}
int get_max(int l,int r,int nowl,int nowr,int p){//求区间最大值
	if(l<=nowl&&nowr<=r){
		return tree[p].maxnum;
	}
	int mid=(nowl+nowr)/2,maxnum=-100000000;
	if(mid>=l) maxnum=max(maxnum,get_max(l,r,nowl,mid,p*2));
	if(mid<r) maxnum=max(maxnum,get_max(l,r,mid+1,nowr,p*2+1));
	return maxnum;
}
int get_id(int l,int r,int nowl,int nowr,int p){//求区间最大值的下标
	if(l<=nowl&&nowr<=r){
		return tree[p].id;
	}
	int mid=(nowl+nowr)/2,maxnum=-100000000,maxid=-10000000;
	if(mid>=l){
		int lmax=get_max(l,r,nowl,mid,p*2);
		if(lmax>=maxnum){
			maxnum=lmax;
			maxid=get_id(l,r,nowl,mid,p*2);
		}
	}
	if(mid<r){
		int rmax=get_max(l,r,mid+1,nowr,p*2+1);
		if(rmax>maxnum){
			maxnum=rmax;
			maxid=get_id(l,r,mid+1,nowr,p*2+1);
		}
	}
	return maxid;
}
void update(int l,int r,int nowl,int nowr,int k,int p){
	if(l<=nowl&&nowr<=r){
		tree[p].maxnum+=k;
		return;
	}
	int mid=(nowl+nowr)/2;
	if(mid>=l) update(l,r,nowl,mid,k,p*2);
	if(mid<r) update(l,r,mid+1,nowr,k,p*2+1);
	if(tree[p*2].maxnum>=tree[p*2+1].maxnum){
		tree[p].maxnum=tree[p*2].maxnum;
		tree[p].id=tree[p*2].id;
	}
	else{
		tree[p].maxnum=tree[p*2+1].maxnum;
		tree[p].id=tree[p*2+1].id;
	}
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++) cin>>a[i];
	build(1,n,1);
	while(m--){
		int l,r,v;
		cin>>l>>r>>v;
		int id=get_id(l,r,1,n,1);//记录最大值的下标
		update(id,id,1,n,-v,1);
	}
	for(int i=1;i<=n;i++){
		cout<<get_max(i,i,1,n,1)<<" ";
	}
}

谢谢!

2021/4/8 14:05
加载中...