题目大意:
一列火车可以坐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;
}