您的位置:首页 > 其它

bzoj 4364: [IOI2014]wall砖墙

2017-10-01 16:09 253 查看

题意:

维护一段序列,可以将区间所有小于h的改为h,大于h的改为h。

题解:

最假女选手?!

这数据范围分块炸裂。

偷听一波知道是线段树。

考虑维护最大最小值,那么对当前节点的修改就很好写的。

关键是怎么将标记下传。

一开始,我想打上处于那种状态(op=1或2)

然后发现不太正确。

既然一个标记不行,那么就上两个嘛。

分成op1,op2,表示两种操作。

于是好像就可行了。

貌似还有一个问题,操作似乎是有顺序的。

但认真思考一下,可以发现是无所谓的,因为父亲节点已经保存了当前这段区间的上下界。

code:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
struct trnode{
int lc,rc,max,min,op1,op2;
}tr[4000010];int tot=0;
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int bt(int l,int r)
{
int x=++tot;
if(l!=r)
{
int mid=(l+r)/2;
tr[x].lc=bt(l,mid);
tr[x].rc=bt(mid+1,r);
}
return x;
}
void mymin(int &x,int y){x=min(x,y);}
void mymax(int &x,int y){x=max(x,y);}
void pushdown(int x)
{
int c,lc=tr[x].lc,rc=tr[x].rc;
if(tr[x].op2!=0)
{
mymin(tr[lc].max,tr[x].max);mymin(tr[lc].min,tr[x].max);
mymin(tr[rc].max,tr[x].max);mymin(tr[rc].min,tr[x].max);
tr[lc].op2=tr[rc].op2=1;
}
if(tr[x].op1!=0)
{
mymax(tr[lc].max,tr[x].min);mymax(tr[lc].min,tr[x].min);
mymax(tr[rc].max,tr[x].min);mymax(tr[rc].min,tr[x].min);
tr[lc].op1=tr[rc].op1=1;
}
tr[x].op1=tr[x].op2=0;
}
void update(int x,int h,int op)
{
if(op==1)
{
mymax(tr[x].max,h);
mymax(tr[x].min,h);
}
else
{
mymin(tr[x].max,h);
mymin(tr[x].min,h);
}
}
void change(int x,int l,int r,int fl,int fr,int h,int op)
{
if(fl==l&&r==fr)
{
update(x,h,op);
if(op==1) tr[x].op1=1;
else tr[x].op2=1;
return;
}
if(tr[x].op1!=0||tr[x].op2!=0) pushdown(x);
int mid=(l+r)/2;
if(fr<=mid) change(tr[x].lc,l,mid,fl,fr,h,op);
else if(fl>mid) change(tr[x].rc,mid+1,r,fl,fr,h,op);
else change(tr[x].lc,l,mid,fl,mid,h,op),change(tr[x].rc,mid+1,r,mid+1,fr,h,op);
tr[x].max=max(tr[tr[x].lc].max,tr[tr[x].rc].max);
tr[x].min=min(tr[tr[x].lc].min,tr[tr[x].rc].min);
}
void print(int x,int l,int r)
{
if(l==r){printf("%d\n",tr[x].max);return;}
pushdown(x);
int mid=(l+r)/2;
print(tr[x].lc,l,mid);print(tr[x].rc,mid+1,r);
}
int main()
{
int n,m;n=read();m=read();
bt(1,n);
while(m--)
{
int op,l,r,h;op=read();l=read();r=read();h=read();
change(1,1,n,l+1,r+1,h,op);
}
print(1,1,n);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: