HDU3577Fast Arrangement(最大值线段树+区间更新)

Chinese always have the railway tickets problem because of its' huge amount of passangers and stations. Now goverment need you to develop a new tickets query system. 
One train can just take k passangers. And each passanger can just buy one ticket from station a to station b. Each train cannot take more passangers any time. The one who buy the ticket earlier which can be sold will always get the ticket. 

Input

The input contains servel test cases. The first line is the case number. In each test case: 
The first line contains just one number k( 1 ≤ k ≤ 1000 ) and Q( 1 ≤ Q ≤ 100000 ) 
The following lines, each line contains two integers a and b, ( 1 ≤ a < b ≤ 1000000 ), indicate a query. 
Huge Input, scanf recommanded.

Output

For each test case, output three lines: 
Output the case number in the first line. 
If the ith query can be satisfied, output i. i starting from 1. output an blank-space after each number. 
Output a blank line after each test case.

Sample Input

1
3 6
1 6
1 6
3 4
1 5
1 2
2 4

Sample Output

Case 1:
1 2 3 5 

火车的载重人数为k人,乘客买从a到b的火车票,超重就不能买票了,注意[a,b),左闭右开区间

线段树“”最大值“”构建,每次上车一人,更新+1,利用懒标记,减少时间复杂度。

注意超重,就不能上车了。

线段树模板题(最大值构造线段树)注意懒标记每次+1,向下传递懒标记时  和求和构造线段树 要区分,传的是什么

 

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	static int T,k,Q,a,b;
	static int Max=0;
	static int N=1000001;
	static boolean[] book=new boolean[100009];//标记是否可以上车
	static int[] tree=new int[4000009];//存储线段树
	static int[] lazy=new int[4000009];//存储懒标记
	static void update_tree(int node,int start,int end,int L,int R){
		if(L<=start&&R>=end){//左右子树被完全包含在区间内
			lazy[node]+=1;//更新懒标记
			tree[node]+=1;//更新懒标记,注意是最大值,不是求和,+1即可
			return;
		}		
		int mid=(start+end)>>1;
		int left_node=2*node;
		int right_node=2*node+1;
		push_down(node,start,end);//向下传递懒标记,因为左右子树没被完全包含在区间内
		if(R<=mid){//全在左子树
			update_tree(left_node,start,mid,L,R);
		}else if(L>mid){//全在右子树
			update_tree(right_node,mid+1,end,L,R);
		}else{//左右子树各有一部分
			update_tree(left_node,start,mid,L,R);
			update_tree(right_node,mid+1,end,L,R);
		}
		tree[node]=Math.max(tree[left_node],tree[right_node]);//最大值构造线段树
	}
	static void push_down(int node,int start,int end){
		if(lazy[node]==0) return;
		
		int left_node=2*node;
		int right_node=2*node+1;
		lazy[left_node]+=lazy[node];
		tree[left_node]+=lazy[node];//不用求和,加上即可,注意理解最大值线段树
		lazy[right_node]+=lazy[node];
		tree[right_node]+=lazy[node];
		lazy[node]=0;
		return;
	}
	static int query_tree(int node,int start,int end,int L,int R){		
		if(L<=start&&R>=end){
			return tree[node];
		}
		push_down(node,start,end);//向下传递懒标记,因为左右子树没被完全包含在区间内
		int mid=(start+end)>>1;
		int left_node=2*node;
		int right_node=2*node+1;
			
		int sum=0;
		if(R<=mid){//与更新类似
			return query_tree(left_node,start,mid,L,R);
		}else if(L>mid){
			return query_tree(right_node,mid+1,end,L,R);
		}else{
			return Math.max(query_tree(left_node,start,mid,L,R),query_tree(right_node,mid+1,end,L,R));
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		T=sc.nextInt();
		int t=1;
		while(T>0){
			Arrays.fill(book, false);
			Arrays.fill(tree,0);
			Arrays.fill(lazy,0);
			k=sc.nextInt();
			Q=sc.nextInt();
			for(int i=1;i<=Q;i++){
				a=sc.nextInt();
				b=sc.nextInt();
				int sum=query_tree(1,1,N,a,b-1);
				if(sum<k){//判断车上人数是否还能上乘客
					update_tree(1,1,N,a,b-1);//可以上人,更新注意右边界
					book[i]=true;//标记可以上车
				}								
			}	
			System.out.println("Case "+t+":");
			for(int i=1;i<=Q;i++){ 
				if(book[i]==true)
					System.out.print(i+" ");
			}
			System.out.println();
			System.out.println();
			
			T--;
			t++;
		}
	}

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值