• hdu 2795-Billboard


    Billboard

    Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 10674    Accepted Submission(s): 4727


    Problem Description
    At the entrance to the university, there is a huge rectangular billboard of size h*w (h is its height and w is its width). The board is the place where all possible announcements are posted: nearest programming competitions, changes in the dining room menu, and other important information.

    On September 1, the billboard was empty. One by one, the announcements started being put on the billboard.

    Each announcement is a stripe of paper of unit height. More specifically, the i-th announcement is a rectangle of size 1 * wi.

    When someone puts a new announcement on the billboard, she would always choose the topmost possible position for the announcement. Among all possible topmost positions she would always choose the leftmost one.

    If there is no valid location for a new announcement, it is not put on the billboard (that's why some programming contests have no participants from this university).

    Given the sizes of the billboard and the announcements, your task is to find the numbers of rows in which the announcements are placed.
     

    Input
    There are multiple cases (no more than 40 cases).

    The first line of the input file contains three integer numbers, h, w, and n (1 <= h,w <= 10^9; 1 <= n <= 200,000) - the dimensions of the billboard and the number of announcements.

    Each of the next n lines contains an integer number wi (1 <= wi <= 10^9) - the width of i-th announcement.
     

    Output
    For each announcement (in the order they are given in the input file) output one number - the number of the row in which this announcement is placed. Rows are numbered from 1 to h, starting with the top row. If an announcement can't be put on the billboard, output "-1" for this announcement.
     

    Sample Input
    3 5 5 2 4 3 3 3
     

    Sample Output
    1 2 1 3 -1
     【题意】: 给你一块 w*h 的板,然后让你用一些 1*x 的木块去填,每次填的时候总是选择行靠前的,假设能够放在该行上。则会选择列靠前的,如今让你对每一种木块 输出它所放在的行。假设不能放上去则输出 -1

    【分析】: 这题一開始看到数据范围是 10^9 吓了一跳。只是细致分析能够发现,事实上真正实用的仅仅是 min(h,n) 其他都是浪费的,那么好了,就能够往下做了 非常明显的是一个区间染色问题。也非常easy的就想到能够用线段树来搞 只是这题是分成若干段后的染色。一開始可能会认为可能须要建立多个线段树来针对每一段分别来搞 实际上,这题仅仅须要一个线段树就能够搞定了 建一棵 [1,len] len=min(h,n) 的线段树,每个线段维护一个最大长度域 maxLen(这里因为不同组之间的线段是不能拼在一起的,因此维护的时候仅仅要简单的 max 一下即可了,不须要左右的讨论。再维护两个域 lmax,rmax)。一開始的时候 maxLen 都为 w 。然后维护这个域的时候仅仅须要简单的 max 一下即可了(每一行事实上都是独立的。用线段树维护的仅仅是能够方便的找到最优的行的位置) 之后就是利用二分逼近的思想来查找那个符合条件的最优行的位置,找到之后做出对应的改动。即 update 该行的 maxLen 域即可了 
    代码:
    #include<cstdio> 
    #include<iostream>
    using namespace std;
    #define maxn 200005 
    #define L(i) (i<<1) 
    #define R(i) (i<<1|1) 
    int h,w,n; 
    struct node 
    {
    	int left,right,len;
    };
    inline int max(int a,int b)
    {
    	return a>b?a:b;
    }
    inline int min(int a,int b)
    {
    	return a<b?a:b;
    }
    struct SegTree 
    { 
    	node tree[maxn*4];
    	void update(int p)
    	{ 
    		tree[p].len=max(tree[L(p)].len,tree[R(p)].len);
    	}
    	void build(int p,int left,int right)
    	{
    		tree[p].left=left;
    		tree[p].right=right;
    		tree[p].len=w;
    		if(left==right) return;
    		int mid=(left+right)>>1;
    		build(L(p),left,mid);
    		build(R(p),mid+1,right);
    	}
    	void query(int p,int x,int& ans)
    	{
    		if(tree[p].len<x)
    		{
    			ans=-1;
    			return;
    		};
    		if(tree[p].left==tree[p].right)
    		{
    			tree[p].len-=x;
    			ans=tree[p].left;
    			return;
    		}
    		if(tree[L(p)].len>=x)
    			query(L(p),x,ans); //这个地方等号要等到才行
    		else if(tree[R(p)].len>=x) 
    			query(R(p),x,ans);
    		update(p);
    	}
    }seg;
    int main()
    {
    	int i,j,k,len,ans;
    	while(scanf("%d%d%d",&h,&w,&n)!=EOF)
    	{
    		len=min(h,n);
    		seg.build(1,1,len);
    		while(n--)
    		{
    			scanf("%d",&k);
    			ans=-1;
    			seg.query(1,k,ans);
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }  
    

  • 相关阅读:
    第三章第四章总结
    java学习2打架代码编写
    windows server 2008 远程桌面(授权、普通用户登录)
    Windows组建网络服务 ——WEB服务器的组建与架构
    windows server 2008 站点系列
    将 Ubuntu 加入到 Windows 2003 AD域
    Windows Server 2008组策略管理与配置
    AD用户设置系列
    利用windows 2003实现服务器群集的搭建与架设
    server2008 跨进新的平台(三)高端的备份还原工具
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5058956.html
Copyright © 2020-2023  润新知