hdu 3577 Fast Arrangement(线段树+lazy)

题目大意:

        一列火车可以坐k个人,有n个乘客按顺序上车,每个乘客要乘坐的区间是[ai,bi],如果乘客要乘坐的区间上有一站火车上人是满的,则这个乘客不能乘车,输出可以乘车的乘客序列。

        抽象一下就是,存在一个上限k,有q个区间,如果区间[ai,bi]中的最大值小于k,则给这个区间加1,输出i,否则什么都不做。

解题思路:

        将题目抽象后就是一个基础的带lazy的线段树,每个节点记录区间的最大值,lazy记录未向下更新的值。

注意点:

        乘坐区间a到b其实是,a到b-1,因为在b站的时候下车,所以b这个点不算是乘客的乘车区间。

代码:

#include <stdio.h>
#include <iostream>

using namespace std;

struct node{
    int l,r,maxN,lazy;
};

node tree[4000005];
int k,q,t,l,r;

void buildTree(int root,int l,int r){
    tree[root].l = l;
    tree[root].r = r;
    tree[root].maxN = 0;
    tree[root].lazy = 0;
    if(l != r){
        int mid = (l+r)/2;
        buildTree(2*root,l,mid);
        buildTree(2*root+1,mid+1,r);
    }
}

void push_down(int root){
    if(!tree[root].lazy) return;
    tree[2*root].maxN += tree[root].lazy;
    tree[2*root].lazy += tree[root].lazy;
    tree[2*root+1].maxN += tree[root].lazy;
    tree[2*root+1].lazy += tree[root].lazy;
    tree[root].lazy = 0;
}

void push_up(int root){
    tree[root].maxN = max(tree[2*root].maxN,tree[2*root+1].maxN);
}

void updata(int root,int l,int r){
    if(tree[root].l == l && tree[root].r == r){
        tree[root].maxN ++;
        tree[root].lazy ++;
        return;
    }
    push_down(root);
    int mid = (tree[root].l + tree[root].r) / 2;
    if(r <= mid){
        updata(2*root,l,r);
    }
    else if(l > mid){
        updata(2*root+1,l,r);
    }
    else{
        updata(2*root,l,mid);
        updata(2*root+1,mid+1,r);
    }
    push_up(root);
}

int query(int root,int l,int r){
    if(tree[root].l == l && tree[root].r == r){
        return tree[root].maxN;
    }
    push_down(root);
    int mid = (tree[root].l + tree[root].r) / 2;
    if(r <= mid){
        return query(2*root,l,r);
    }
    else if(l > mid){
        return query(2*root+1,l,r);
    }
    else{
        return max(query(2*root,l,mid),query(2*root+1,mid+1,r));
    }

}

int main()
{
    scanf("%d",&t);
    for(int loop = 1; loop <= t; loop ++){
        scanf("%d%d",&k,&q);
        buildTree(1,1,1000000);
        printf("Case %d:\n",loop);
        for(int i = 1; i <= q; i ++){
            scanf("%d%d",&l,&r);
            r--;
            if(query(1,l,r) < k){
                updata(1,l,r);
                printf("%d ",i);
            }
        }
        printf("\n\n");
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值