社区讨论

线段树0pts求条,每个子任务对一点

P4560[IOI 2014] Wall 砖墙参与者 1已保存回复 1

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
1 条
当前快照
1 份
快照标识符
@mkhyzvgk
此快照首次捕获于
2026/01/17 15:12
上个月
此快照最后确认于
2026/01/19 23:35
上个月
查看原帖
CPP
#include<bits/stdc++.h>
using namespace std;
struct node{
	int l,r,maxx,minn,tag1,tag2,tag3,tag4;
}tree[8000010];
int n,m;
void pushup(int p){
	tree[p].maxx=max(tree[p*2].maxx,tree[p*2+1].maxx);
	tree[p].minn=min(tree[p*2].minn,tree[p*2+1].minn);
}
void build(int p,int l,int r){
	tree[p].l=l,tree[p].r=r;
	tree[p].maxx=INT_MIN;
	tree[p].minn=INT_MAX;
	tree[p].tag1=tree[p].tag2=tree[p].tag3=tree[p].tag4=0;
	if(l==r){
		tree[p].maxx=0;
		tree[p].minn=0;
		tree[p].tag1=tree[p].tag2=tree[p].tag3=tree[p].tag4=0;
		return;
	}
	int mid=(l+r)>>1;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
	pushup(p);
}
void pushdown(int p){
	if(tree[p].tag1){
		tree[p*2].tag1=tree[p].tag1;
		tree[p*2].maxx=tree[p].tag1;
		tree[p*2].minn=tree[p].tag1;//区间被完全修改,里面所有的数一开始都小于h因此最小值和最大值都变成h 
		tree[p*2+1].tag1=tree[p].tag1;
		tree[p*2+1].maxx=tree[p].tag1;
		tree[p*2+1].minn=tree[p].tag1;
		tree[p].tag1=0;
	}
	if(tree[p].tag2){//处理部分修改 
		tree[p*2].tag2=tree[p].tag2;
		tree[p*2].maxx=max(tree[p*2].maxx,tree[p].tag2);//注意这里有变动 
		tree[p*2].minn=max(tree[p].tag2,tree[p*2].minn);//这个左子树区间里面所有的数都不小于h了,故最小值就是h
		tree[p*2+1].tag2=tree[p].tag2;
		tree[p*2+1].maxx=max(tree[p*2+1].maxx,tree[p].tag2);
		tree[p*2+1].minn=max(tree[p].tag2,tree[p*2+1].minn);
		tree[p].tag2=0;
	}
	if(tree[p].tag3){
		tree[p*2].tag3=tree[p].tag3;
		tree[p*2].minn=tree[p].tag3;
		tree[p*2].maxx=tree[p].tag3;
		tree[p*2+1].tag3=tree[p].tag3;
		tree[p*2+1].minn=tree[p].tag3;
		tree[p*2+1].maxx=tree[p].tag3;
		tree[p].tag3=0;
	}
	if(tree[p].tag4){
		tree[p*2].tag4=tree[p].tag4;
		tree[p*2].minn=min(tree[p*2].minn,tree[p].tag4);//注意这里有变动 
		tree[p*2].maxx=min(tree[p].tag4,tree[p*2].maxx);
		tree[p*2+1].tag4=tree[p].tag4;
		tree[p*2+1].minn=min(tree[p*2+1].minn,tree[p].tag4);
		tree[p*2+1].maxx=min(tree[p].tag4,tree[p*2+1].maxx);
		tree[p].tag4=0;
	}
}
void change1(int p,int l,int r,int h){
	if(tree[p].l>=l&&tree[p].r<=r){
		if(tree[p].maxx<=h) tree[p].maxx=h,tree[p].tag1=h,tree[p].minn=h;//tag1表示这个区间完全修改的懒标签,
		else if(tree[p].minn<=h) tree[p].tag2=h,tree[p].minn=h;//tag2则表示部分修改 
		return;
	}
	pushdown(p);
	int mid=(tree[p].l+tree[p].r)>>1;
	if(l<=mid) change1(p*2,l,r,h);
	if(r>mid) change1(p*2+1,l,r,h);
	pushup(p);
}
void change2(int p,int l,int r,int h){
	if(tree[p].l>=l&&tree[p].r<=r){
		if(tree[p].minn>=h) tree[p].minn=h,tree[p].tag3=h,tree[p].maxx=h;//tag3表示这个区间被完全修改的标签
		else if(tree[p].maxx>=h) tree[p].tag4=h,tree[p].maxx=h;//tag4表示部分修改
		return; 
	}
	pushdown(p);
	int mid=(tree[p].l+tree[p].r)>>1;
	if(l<=mid) change2(p*2,l,r,h);
	if(r>mid) change2(p*2+1,l,r,h);
	pushup(p);
} 
void query(int p,int x){
	if(tree[p].l>x) return;
	if(tree[p].r<x) return;
	if(tree[p].l==tree[p].r&&tree[p].l==x){
		cout<<max(0,tree[p].minn)<<endl;
		return;
	}
	pushdown(p);
	query(p*2,x);
	query(p*2+1,x);
}
/*
0 0 0 0 0
->1 3 max5
//5 5 5 0 0
tag[1,2]->5
tag[3,3]->5
->3 4 max4
->tag[3,4]->4
   [1,5]
[1,3][4,5]
[1,2][3,3]
*/
int main(){
	cin>>n>>m;
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int opt,l,r,h;
		cin>>opt>>l>>r>>h;
		l++,r++;
		if(opt==1) change1(1,l,r,h);
		else if(opt==2) change2(1,l,r,h);
		//for(int j=1;j<=n;j++){
		//	query(1,j);
		//	cout<<endl;
		//}
		//cout<<endl;
	}
	for(int i=1;i<=n;i++) query(1,i);
	return 0;
}

回复

1 条回复,欢迎继续交流。

正在加载回复...