南二的公告牌
Total Submit:360 Accepted:19
Description
南二有一个巨大的长方形公告牌,尺寸为h×w(h是它的高度,w是它的宽度)。牌子上可以张贴一切可能的告示:最近ACM程序设计竞赛通知,食堂菜单的变化,以及其他重要信息。
在9月1日,公告牌是空的。告示一个接一个地张贴在广告牌上。
每个告示是单位高度的纸条。具体地说,第i个告示是一个大小1 ×wi的矩形。当有人在公告牌上贴出一个新的告示,他永远选择尽可能上的位置。在所有可能的最高位置,她将永远选择最左边的一个。
如果没有有效的位置来贴一个新的告示,则不放在公告牌上。给定公告牌的大小,你的任务是找到告示放置的行数。
Input
输入文件的第一行包括三个整数:h, w, 和 n (1 ≤ h,w ≤ 109; 1 ≤ n ≤ 200 000) —表示公告牌的大小和告示的数目。
下面n行,每行包括一个整数wi (1 ≤wi ≤ 109) 表示 第i个告示的宽度。
Output
对于每个告示(按照它们在输入文件中给定的顺序)输出一个值 — 这个告示放置的行数。行从1到h标识,从顶行开始。如果一个告示不能放置于告示牌,则输出“-1”。
注意:输出部分的结尾要求包含一个多余的空行。
Sample Input
3 5 5
2
4
3
3
3
Sample Output
1
2
1
3
-1
Source
“IBM南邮杯”个人赛2009
分析:线段树+单点更新。很重要,要掌握。
一开始自己写的提交Test15一直超时。想想应该是我的update写的不太好。
然后应用了query+update比较标准的写法就AC了。
一开始的代码(错误的):其实我想多了。确实会超时,都没用到mid
#include<iostream>
using namespace std;
#define MIN(a, b) (a<b?a:b)
#define MAX(a, b) (a>b?a:b)
//南二的公告牌
__int64 h, w;
int n;
bool flag; // 只需一次
struct Node
{
int l;
int r;
__int64 value; // 该子树下最大空余
}tree[800004];
void build(int v, int l, int r)
{
tree[v].l = l;
tree[v].r = r;
tree[v].value = w;
if(l == r) return;
int mid = (l+r)>>1;
build(v<<1, l, mid);
build(v<<1|1, mid+1, r);
}
void update(int v, int wi, int curr)
{
if(tree[1].value < wi)
{
printf("-1\n");
return;
}
if(tree[v].value >= wi && tree[v].l == tree[v].r)
{
if(flag == true)
{
tree[v].value -= wi;
printf("%d\n",tree[v].l); // l == r
flag = false;
return;
}
}
if(tree[v<<1].value >= wi) update(v<<1, wi, curr<<1);
if(tree[v<<1|1].value >= wi) update(v<<1|1, wi, curr<<1|1);
if(tree[curr].l != tree[curr].r)
tree[curr].value = MAX(tree[curr<<1].value, tree[curr<<1|1].value);
}
int main()
{
__int64 wi;
scanf("%64I%64I%d",&h,&w,&n);
build(1, 1, MIN(h, n));
while(n --)
{
scanf("%d",&wi);
flag = true;
update(1, wi, 1);
}
return 0;
}
void update(int v, int l, int curr) // l == r
{
if(tree[v].l == l && tree[v].r == l)
{
tree[v].value -= wi;
return;
}
int mid = (tree[v].l+tree[v].r)>>1;
if(l <= mid)
update(v<<1, l, curr<<1);
else if(l > mid)
update(v<<1|1, l, curr<<1|1);
tree[curr].value = MAX(tree[curr<<1].value, tree[curr<<1|1].value);
}
int query(int v, int l, int r)
{
if(tree[v].value < wi) return -1;
if(tree[v].l == tree[v].r) return tree[v].l;
int mid = (tree[v].l+tree[v].r)>>1;
if(tree[v<<1].value >= wi)
return query(v<<1, l, mid);
else
return query(v<<1|1, mid+1, r);
}