线段树——区间合并

来源:互联网 发布:大数据行业分析 编辑:程序博客网 时间:2024/06/01 09:09

题目:Hotel

题意:区间初始全0。两种操作:将区间某一段置0;查询超过指定长度的区间的最左端点(多个区间则取最左)

第一次做错,错在查询时,只是查询整个区间的最长连续子区间,可题目要求的只是超过一定长度的子区间,而不一定是最长的,所以应按左区间,跨左右区间,右区间的顺序递归查找满足要求的子区间。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define MAXN 50000#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int msum[MAXN<<2],lsum[MAXN<<2],rsum[MAXN<<2];int lable[MAXN<<2],idm[MAXN<<2];void pushUp(int l,int r,int rt) {//合并子区间    int m=(l+r)>>1;    lsum[rt]=lsum[rt<<1]==m-l+1?m-l+1+lsum[rt<<1|1]:lsum[rt<<1];    rsum[rt]=rsum[rt<<1|1]==r-m?r-m+rsum[rt<<1]:rsum[rt<<1|1];    msum[rt]=max(max(msum[rt<<1],msum[rt<<1|1]),rsum[rt<<1]+lsum[rt<<1|1]);//    if(msum[rt]==msum[rt<<1]) idm[rt]=idm[rt<<1];//    else if(msum[rt]==rsum[rt<<1]+lsum[rt<<1|1]) idm[rt]=m-rsum[rt<<1]+1;//    else idm[rt]=idm[rt<<1|1];}void pushDown(int l,int r,int rt) {//标记下放    if(~lable[rt]) {        int m=(l+r)>>1;        lable[rt<<1]=lable[rt<<1|1]=lable[rt];        msum[rt<<1]=lsum[rt<<1]=rsum[rt<<1]=lable[rt]*(m-l+1);//1清空 0占满        msum[rt<<1|1]=lsum[rt<<1|1]=rsum[rt<<1|1]=lable[rt]*(r-m);//        if(lable[rt]) idm[rt<<1]=l,idm[rt<<1|1]=m+1;//        else idm[rt<<1]=idm[rt<<1|1]=-1;        lable[rt]=-1;    }}void build(int l,int r,int rt) {    msum[rt]=lsum[rt]=rsum[rt]=r-l+1;    lable[rt]=-1;//    idm[rt]=l;    if(l==r) return ;    int m=(l+r)>>1;    build(lson);    build(rson);}void update(int x,int y,int w,int l,int r,int rt) {    if(x<=l&&r<=y) {        msum[rt]=lsum[rt]=rsum[rt]=w*(r-l+1);        lable[rt]=w;//        idm[rt]=w?l:-1;        return ;    }    pushDown(l,r,rt);    int m=(l+r)>>1;    if(x<=m) update(x,y,w,lson);    if(y>m) update(x,y,w,rson);    pushUp(l,r,rt);}//int query(int w,int l,int r,int rt) {//错误的查询方式//    int m=(l+r)>>1;//    if(msum[rt<<1]>=w) return idm[rt<<1];//    if(rsum[rt<<1]+lsum[rt<<1|1]>=w) return m-rsum[rt<<1]+1;//    return idm[rt<<1|1];//}int query(int w,int l,int r,int rt) {if (l == r) return l;pushDown(l,r,rt);int m = (l + r) >> 1;if (msum[rt<<1] >= w) return query(w , lson);else if (rsum[rt<<1] + lsum[rt<<1|1] >= w) return m - rsum[rt<<1] + 1;return query(w , rson);}int main() {//    ios::sync_with_stdio(false);    int n,m,ins,a,b;    scanf("%d%d",&n,&m);    build(1,n,1);    while(m--) {        cin >> ins;        if(ins==1) {            scanf("%d",&a);            if(msum[1]<a) {puts("0");continue;}            int q=query(a,1,n,1);            printf("%d\n",q);            update(q,q+a-1,0,1,n,1);        }        else {            scanf("%d%d",&a,&b);            update(a,a+b-1,1,1,n,1);        }    }    return 0;}