社区讨论
线段树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 条回复,欢迎继续交流。
正在加载回复...