HDU - 4553 G - 约会安排

HDU - 4553 G - 约会安排

题 意:小明是个屌丝,他有一些朋友和女神来约她玩耍,他总共有t个时间点,n次屌丝朋友的女神的询问。DS QT代表屌丝的需要一段连续的时间段QT来玩耍,如果是屌丝的询问,如果小明还有时间的话就回复 X,let’s fly。否则回复:fly with yourself
NS QT代表女神需要一段连续的时间位QT来玩耍。如果已经没有时间剩下了,那么就占用屌丝请求的时间,如果有则回复:X,don’t put my gezi。否则回复:wait for me。当然小明还有学习,如果询问是STUDY!! L,R。则清空[L,R]女神,屌丝占用的区间。
 当然,我们知道小明不是一个节操负无穷的人,如果和女神约会完,还有剩余时间,他还是会和原来约好的基友去dota的。(举个例子:小西(屌丝)和小明约好在1~5这个时间单位段内打dota,这时候,女神来和小明预约长度为3的时间段,那么最终就是1~3小明去和女神约会,搞定后在4~5和小西打dota)。

数据范围:
1<=Case<=30
1<=T,N<=1e5
1<=QT<=1e5+1e4
1<=L<=R<=T
样例输入:

1
5 6
DS 3
NS 2
NS 4
STUDY!! 1 5
DS 4
NS 2

样例输出:

Case 1:
1,let's fly
4,don't put my gezi
wait for me
I am the hope of chinese chengxuyuan!!
1,let's fly
1,don't put my gezi

思 路:线段树维护最大空闲连续区间。维护两段区间,一段是有人占用的区间,一段是女神占用的区间。对于屌丝的询问,每次在有人占用的区间查询,更行有人占用的区间。对于女神的询问,先在有人占用的区间询问是否有那么多连续的区间。同时更新女神区间,和有人占用的区间。对于Study 则同时清空两端区间。

收 获:对线段树有了更加灵活的运用,对维护最大连续区间的了解更加深刻

#include<bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn = 1e5+5;
struct node{
    int l,r;
    int lmax,rmax,MAX;
    int lmax1,rmax1,MAX1;
}a[maxn<<2];
int n,m;
void PushUp(int rt){
    if(a[rt].l == a[rt].r)return ;
    a[rt].lmax = a[rt<<1].lmax;
    if(a[rt<<1].lmax == a[rt<<1].r-a[rt<<1].l+1) a[rt].lmax = a[rt<<1].lmax + a[(rt<<1)|1].lmax;
    a[rt].rmax = a[(rt<<1)|1].rmax;
    if(a[rt<<1|1].rmax == a[rt<<1|1].r-a[rt<<1|1].l+1) a[rt].rmax = a[(rt<<1)|1].rmax + a[rt<<1].rmax;
    a[rt].MAX = max(a[rt<<1].MAX,a[(rt<<1)|1].MAX);
    a[rt].MAX = max(a[rt].MAX,max(a[rt].lmax,a[rt].rmax)); 
    a[rt].MAX = max(a[rt].MAX,a[rt<<1].rmax + a[(rt<<1)|1].lmax);

    a[rt].lmax1 = a[rt<<1].lmax1;
    if(a[rt<<1].lmax1 == a[rt<<1].r-a[rt<<1].l+1) a[rt].lmax1 = a[rt<<1].lmax1 + a[(rt<<1)|1].lmax1;
    a[rt].rmax1 = a[(rt<<1)|1].rmax1;
    if(a[(rt<<1)|1].rmax1 == a[(rt<<1)|1].r-a[(rt<<1)|1].l+1) a[rt].rmax1 = a[(rt<<1)|1].rmax1 + a[rt<<1].rmax1;
    a[rt].MAX1 = max(a[rt<<1].MAX1,a[rt<<1|1].MAX1);
    a[rt].MAX1 = max(a[rt].MAX1,max(a[rt].lmax1,a[rt].rmax1));
    a[rt].MAX1 = max(a[rt].MAX1,a[rt<<1].rmax1 + a[(rt<<1)|1].lmax1);

}
void PushDown(int rt){
    if(a[rt].l == a[rt].r) return ;
    int Lson = rt<<1,Rson = (rt<<1)|1;
    if(a[rt].MAX == 0){
        a[rt<<1].MAX = a[rt<<1].lmax = a[rt<<1].rmax = 0;
        a[(rt<<1)|1].MAX = a[(rt<<1)|1].lmax = a[(rt<<1)|1].rmax = 0;
    }
    if(a[rt].MAX == a[rt].r - a[rt].l+1){
        a[Lson].MAX = a[Lson].lmax = a[Lson].rmax = a[Lson].r-a[Lson].l+1;
        a[Rson].MAX = a[Rson].lmax = a[Rson].rmax = a[Rson].r-a[Rson].l+1;
    }

    if(a[rt].MAX1 == 0){
        a[rt<<1].MAX1 = a[rt<<1].lmax1 = a[rt<<1].rmax1 = 0;
        a[(rt<<1)|1].MAX1 = a[(rt<<1)|1].lmax1 = a[(rt<<1)|1].rmax1 = 0;
    }
    if(a[rt].MAX1 == a[rt].r - a[rt].l+1){
        a[Lson].MAX1 = a[Lson].lmax1 = a[Lson].rmax1 = a[Lson].r-a[Lson].l+1;
        a[Rson].MAX1 = a[Rson].lmax1 = a[Rson].rmax1 = a[Rson].r-a[Rson].l+1;
    }

}
void build(int l,int r,int rt){
    a[rt].l = l;
    a[rt].r = r;
    a[rt].lmax = a[rt].rmax = a[rt].MAX = r-l+1;
    a[rt].lmax1 = a[rt].rmax1 = a[rt].MAX1 = r-l+1;
    if(l == r)return ;
    int m = (l+r)/2;
    build(lson);
    build(rson);
    PushUp(rt);
}
int query(int rt,int x){
    if(a[rt].MAX < x) return 0;
    if(a[rt].lmax >= x) return a[rt].l;
    if(a[rt<<1].MAX >= x)return query(rt<<1,x);
    if(a[rt<<1].rmax + a[(rt<<1)|1].lmax >= x) return (a[rt<<1].r - a[rt<<1].rmax +1);
    return query((rt<<1)|1,x);
}

int query1(int rt,int x){
    if(a[rt].MAX1 < x)return 0;
    if(a[rt].lmax1 >= x)return a[rt].l;
    if(a[rt<<1].MAX1 >=x) return query1(rt<<1,x);
    if(a[rt<<1].rmax1 + a[(rt<<1)|1].lmax1 >=x)return a[rt<<1].r - a[rt<<1].rmax1+1;
    return query1((rt<<1)|1,x);
}
void update(int L,int R,int rt){
    if(L<=a[rt].l && a[rt].r <= R){
        a[rt].lmax1 = a[rt].rmax1 = a[rt].MAX1 = (a[rt].r - a[rt].l+1);
        a[rt].lmax = a[rt].rmax = a[rt].MAX = (a[rt].r - a[rt].l+1);
        return ;
    }
    PushDown(rt);
    int l = a[rt].l,r = a[rt].r;
    int m = (l+r)/2;
    if(L<=m) update(L,R,rt<<1);
    if(R>m)update(L,R,rt<<1|1);
    PushUp(rt);
}

void zhan1(int L,int R,int rt){
    if(L <= a[rt].l && a[rt].r <= R){
        a[rt].lmax = a[rt].rmax = a[rt].MAX = 0;
        return;
    }
    PushDown(rt);
    int l = a[rt].l,r = a[rt].r;
    int m = (l+r)>>1;
    if(L<=m) zhan1(L,R,rt<<1);
    if(R>m) zhan1(L,R,rt<<1|1);
    PushUp(rt);
}
void zhan2(int L,int R,int rt){
    if(L<=a[rt].l && a[rt].r <= R){
        a[rt].lmax1 = a[rt].rmax1 = a[rt].MAX1 = 0;
        a[rt].lmax = a[rt].rmax = a[rt].MAX = 0;
        return;
    }
    PushDown(rt);
    int l = a[rt].l,r = a[rt].r;
    int m = (l+r)>>1;
    if(L<=m) zhan2(L,R,rt<<1);
    if(R>m)zhan2(L,R,rt<<1|1);
    PushUp(rt);
}


int main(){
    int t,Kase = 0;
    scanf("%d",&t);
    while(t--){
        printf("Case %d:\n",++Kase);
        scanf("%d %d",&n,&m);
        build(1,n,1);
        char s[10];
        int x,y;
        while(m--){
            scanf("%s",s);
            if(s[0] == 'D'){
                scanf("%d",&x);
                int tmp = query(1,x);
                if(tmp == 0){
                    printf("fly with yourself\n");
                }else{
                    zhan1(tmp,tmp+x-1,1);
                    printf("%d,let's fly\n",tmp);
                }
            }else if(s[0] == 'N'){
                scanf("%d",&x);
                int tmp = query(1,x);
                if(tmp!=0){
                    printf("%d,don't put my gezi\n",tmp);
                    zhan2(tmp,tmp+x-1,1);
                    continue;
                }
                tmp = query1(1,x);
                if(tmp == 0){
                    printf("wait for me\n");
                }else{
                    printf("%d,don't put my gezi\n",tmp);
                    zhan2(tmp,tmp+x-1,1);
                }
            }else{
                printf("I am the hope of chinese chengxuyuan!!\n");
                scanf("%d %d",&x,&y);
                update(x,y,1);
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值