1593: [Usaco2008 Feb]Hotel 旅馆

来源:互联网 发布:豪迪软件 编辑:程序博客网 时间:2024/06/02 16:20

题目链接

题目大意:维护01序列,两种操作
1.询问连续长度为x的全0子序列的最左端点,并将其覆盖为1
2.[l,r]覆盖为0

题解:对于每个节点,维护三个量
1.lmx[x]表示从x节点区间左端点开始的全0子序列长度
2.rmx[x]表示从x节点区间右端点开始的全0子序列长度
3.mx[x]表示x节点区间内的全0子序列最大长度

代码中的sum[x]为x节点的区间长度,方便操作

这样就可以维护区间合并了

具体写法见代码

我的收获:

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;#define M 50005#define ls x<<1#define rs x<<1|1#define lson l,m,x<<1 #define rson m+1,r,x<<1|1#define root 1,n,1int n,m;int sum[M<<2],lmx[M<<2],rmx[M<<2],mx[M<<2],tag[M<<2];inline void pushup(int x){    lmx[x]=mx[ls]==sum[ls]?mx[ls]+lmx[rs]:lmx[ls];//左右相连     rmx[x]=mx[rs]==sum[rs]?mx[rs]+rmx[ls]:rmx[rs];    mx[x]=max(max(mx[ls],mx[rs]),rmx[ls]+lmx[rs]);//考虑中间连起来 }void pushdown(int x,int m) {    if(!tag[x]||m==1) return ;    if(tag[x]==1)    {        mx[ls]=lmx[ls]=rmx[ls]=sum[ls];//记得都写上         mx[rs]=lmx[rs]=rmx[rs]=sum[rs];        tag[ls]=tag[rs]=tag[x];    }    else    {        mx[ls]=lmx[ls]=rmx[ls]=0;        mx[rs]=lmx[rs]=rmx[rs]=0;        tag[ls]=tag[rs]=tag[x];    }    tag[x]=0;}void build(int l,int r,int x){    sum[x]=mx[x]=lmx[x]=rmx[x]=r-l+1;    if(l==r) return ;    int m=(l+r)>>1;    build(lson),build(rson);}void updata(int L,int R,int f,int l,int r,int x){    if(L<=l&&r<=R){        if(f==1) mx[x]=lmx[x]=rmx[x]=sum[x];//置为0         else mx[x]=lmx[x]=rmx[x]=0;//置为1         tag[x]=f;return ;    }    pushdown(x,r-l+1);    int m=(l+r)>>1;    if(L<=m) updata(L,R,f,lson);    if(R>m) updata(L,R,f,rson);    pushup(x);}int query(int k,int l,int r,int x){    if(l==r) return l;    pushdown(x,r-l+1);    int m=(l+r)>>1;    if(mx[ls]>=k) return query(k,lson);//优先左儿子     if(rmx[ls]+lmx[rs]>=k) return m-rmx[ls]+1;//其次考虑中间连起来,同时计算端点     return query(k,rson);//都不行就右儿子 }void work(){    int opt,x,y;    for(int i=1;i<=m;i++){        scanf("%d%d",&opt,&x);        if(opt==1){            if(mx[1]<x) {puts("0");continue;}//特判无解             int p=query(x,root);printf("%d\n",p);            updata(p,p+x-1,2,root);        }        else scanf("%d",&y),updata(x,x+y-1,1,root);    }}void init(){    cin>>n>>m;    build(root);}int main(){    init();    work();    return 0;}
阅读全文
0 0