HDU - 4553 约会安排 【线段树区间合并】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4553

需要3个标记,分别是左区间连续长度,右区间连续长度,中间区间的最大连续长度(最大可以通过更新回溯的过程中,pushup中更新)。

题目的难点是如何找合适的连续区间。

因为题目要求的是最左边的符合题目要求的区间,所以找区间的时候要先看左区间的连续长度,其次是中间区间的连续长度(因为中间可能会有多个连续的区间,所以要递归下去找,顺序一样是从左开始找),最后是右区间的连续长度。

代码量可能会很大,所以要细心,耐心一点。

还有需要注意的是输出最好从样例里复制粘贴。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>

using namespace std;

const int Maxn = 1e5+10;
const int mod = 10007;

typedef long long ll;

int DS[Maxn<<2], NS[Maxn<<2], DSmid[Maxn<<2], NSmid[Maxn<<2], DSleft[Maxn<<2], DSright[Maxn<<2],
    NSleft[Maxn<<2], NSright[Maxn<<2];
int L, R, op, ans, len;

void pushdown(int cur, int l, int r) {
    if(NS[cur] == 0) {
        NS[cur<<1] = NS[cur<<1|1] = 0;
        NS[cur] = -1;
        int mid = (r+l)>>1;
        NSmid[cur<<1] = NSleft[cur<<1] = NSright[cur<<1] =  (mid-l+1);
        NSmid[cur<<1|1] = NSleft[cur<<1|1] = NSright[cur<<1|1] = (r-mid);
    }
    if(DS[cur] == 0) {
        DS[cur<<1] = DS[cur<<1|1] = 0;
        DS[cur] = -1;
        int mid = (r+l)>>1;
        DSmid[cur<<1] = DSleft[cur<<1] = DSright[cur<<1] =  (mid-l+1);
        DSmid[cur<<1|1] = DSleft[cur<<1|1] = DSright[cur<<1|1] = (r-mid);
    }
    if(NS[cur] == 1) {
        NS[cur<<1] = NS[cur<<1|1] = NS[cur];
        NS[cur] = -1;
        DSmid[cur<<1] = DSmid[cur<<1|1] = NSmid[cur<<1] = NSmid[cur<<1|1] = 0;
        DSleft[cur<<1] = DSright[cur<<1] = DSleft[cur<<1|1] = DSright[cur<<1|1] = 0;
        NSleft[cur<<1] = NSright[cur<<1] = NSleft[cur<<1|1] = NSright[cur<<1|1] = 0;
    }
    if(DS[cur] == 1) {
        DS[cur<<1] = DS[cur<<1|1] = DS[cur];
        DS[cur] = -1;
        DSmid[cur<<1] = DSmid[cur<<1|1] = 0;
        DSleft[cur<<1] = DSright[cur<<1] = DSleft[cur<<1|1] = DSright[cur<<1|1] = 0;
    }
}

void pushup(int cur, int l, int r) {
    int mid = (r+l)>>1;
    DSleft[cur] = DSleft[cur<<1]; DSright[cur] = DSright[cur<<1|1];
    if(DSleft[cur<<1] == mid-l+1) DSleft[cur] += DSleft[cur<<1|1];
    if(DSright[cur<<1|1] == r-mid) DSright[cur] += DSright[cur<<1];

    NSleft[cur] = NSleft[cur<<1]; NSright[cur] = NSright[cur<<1|1];
    if(NSleft[cur<<1] == mid-l+1) NSleft[cur] += NSleft[cur<<1|1];
    if(NSright[cur<<1|1] == r-mid) NSright[cur] += NSright[cur<<1];

    DSmid[cur] = DSright[cur<<1]+DSleft[cur<<1|1];
    DSmid[cur] = max(DSmid[cur<<1], DSmid[cur]);
    DSmid[cur] = max(DSmid[cur<<1|1], DSmid[cur]);

    NSmid[cur] = NSright[cur<<1]+NSleft[cur<<1|1];
    NSmid[cur] = max(NSmid[cur<<1], NSmid[cur]);
    NSmid[cur] = max(NSmid[cur<<1|1], NSmid[cur]);
}

void updata(int cur, int l, int r) {
    if(L <= l && r <= R) {
        if(op == 1) {
            DS[cur] = 1;
            DSmid[cur] = DSleft[cur] = DSright[cur] = 0;
        } else if(op == 2){
            NS[cur] = 1;
            DSmid[cur] = DSleft[cur] = DSright[cur] = 0;
            NSmid[cur] = NSleft[cur] = NSright[cur] = 0;
        } else {
            DS[cur] = NS[cur] = 0;
            DSmid[cur] = NSmid[cur] = (r-l+1);
            NSleft[cur] = NSright[cur] = DSleft[cur] = DSright[cur] = (r-l+1);
        }
        return;
    }

    int mid = (r+l)>>1;

    pushdown(cur, l, r);

    if(L <= mid) updata(cur<<1, l, mid);
    if(mid+1 <= R) updata(cur<<1|1, mid+1, r);

    pushup(cur, l, r);
}

void DSquery(int cur, int l, int r) {
    if(ans != -1) return;
    if(DSleft[cur] >= len) ans = l;
    else if(DSmid[cur] >= len) {
        int mid = (l+r)>>1;
        pushdown(cur, l , r);
        DSquery(cur<<1, l, mid);
        if(DSright[cur<<1]+DSleft[cur<<1|1] >= len && ans == -1) ans = DSright[cur<<1] == 0 ? mid+1 : mid-DSright[cur<<1]+1;
        DSquery(cur<<1|1, mid+1, r);
    } else if(DSright[cur] >= len) ans = r-(DSright[cur])+1;
}

void NSquery(int cur, int l, int r) {
    if(ans != -1) return;
    if(NSleft[cur] >= len) ans = l;
    else if(NSmid[cur] >= len) {
        int mid = (l+r)>>1;
        pushdown(cur, l , r);
        NSquery(cur<<1, l, mid);
        if(NSright[cur<<1]+NSleft[cur<<1|1] >= len && ans == -1) ans = NSright[cur<<1] == 0 ? mid+1 : mid-NSright[cur<<1]+1;
        NSquery(cur<<1|1, mid+1, r);
    } else if(NSright[cur] >= len) ans = r-(NSright[cur])+1;
}

int main(void)
{
    int t, T, M;
    scanf("%d", &t);
    for(int cas = 1; cas <= t; ++cas) {
        scanf("%d%d", &T, &M);
        memset(DS, -1, sizeof(DS));
        memset(NS, -1, sizeof(NS));
        memset(DSmid, 0, sizeof(DSmid));
        memset(NSmid, 0, sizeof(NSmid));
        op = 3; L = 1; R = T;
        updata(1, 1, T);

        printf("Case %d:\n", cas);
        char ch[20];
        while (M--) {
            scanf("%s", ch); ans = -1;
            if(!strcmp(ch, "DS")) {
                scanf("%d", &len);
                DSquery(1, 1, T);
                if(ans == -1) printf("fly with yourself\n");
                else {
                    printf("%d,let's fly\n", ans);
                    L = ans; R = ans+len-1; op = 1;
                    updata(1, 1, T);
                }
            } else if(!strcmp(ch, "NS")) {
                scanf("%d", &len);
                DSquery(1, 1, T);
                if(ans != -1) {
                    printf("%d,don't put my gezi\n", ans);
                    L = ans; R = ans+len-1; op = 2;
                    updata(1, 1, T);
                } else {
                    NSquery(1, 1, T);
                    if(ans == -1) printf("wait for me\n");
                    else {
                       printf("%d,don't put my gezi\n", ans);
                        L = ans; R = ans+len-1; op = 2;
                        updata(1, 1, T);
                    }
                }
            } else {
                scanf("%d%d", &L, &R);
                printf("I am the hope of chinese chengxuyuan!!\n");
                op = 3; updata(1, 1, T);
            }
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值