题目链接:hdu2795
这道题数据量太大,要是一般的暴力简单遍历,结果是 Time Limit Exceeded(我试过)。
由于 109 太大了,无法用定义长度为h(广告牌的高)的数组,于是看了看输入,只有200000组数据,就是说最多放200000行公告,于是可以把200000作为数组长度。
没有用线段树的超时代码
没有用线段树代码,超时
/***
* hdu2795
* 来来来,暴力一下怎么样??
* Time Limit Exceeded
*/
#include<iostream>
#include<string>
#include<cstdio>
#include<algorithm>
using namespace std;
const int mmax = 200002;
int val[mmax];
int board[mmax];
int main()
{
int h, w, n;
while(scanf("%d%d%d",&h, &w, &n) == 3)
{
memset(val, 0, sizeof(val));
memset(board, 0, sizeof(board));
for(int i = 1; i <= n; i++)
scanf("%d", &val[i]);
for(int i = 1; i <= n; i++)
{
int j;
for(j = 1; j <= h; j++)
{
if(w-board[j] < val[i])
continue;
board[j] += val[i];
printf("%d\n", j);
break;
}
if(j == h+1)
printf("-1\n");
}
}
}
用了线段树的AC代码
关于-1的情况可以在根结点处理,如果在函数中(我用的叫做query()函数)处理,可能导致wa。
建树的大小是有讲究的, if(h > n) h = n; build(1, 1, h); 这样做可以防止建树过大。
用了线段树代码,ac
/***
* 线段树第三弹
* 看似和区间没啥关系的线段树
* ac
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lc (d<<1)
#define rc (d<<1|1)
#define mid (l+r>>1)
const int mmax = 200002;
int val[mmax];
struct tree
{
int v;
}tr[mmax<<2];//既然用了线段树,虽然结构体只有一个int v,但还是用结构体而不用数组
//建树,当然你可以直接memset(tr, 0, sizeof(tr));
void build(int d, int l, int r)
{
if(l == r)
{
tr[d].v = 0;
return;
}
build(lc, l, mid);
build(rc, mid+1, r);
tr[d].v = 0;
}
void query(int d, int l, int r, int w , int x)
{
if(l == r)
{
tr[d].v += x;//注意要+=
printf("%d\n", l);
return;
}
if(tr[lc].v + x <= w)//必须先左后右
{
query(lc, l, mid, w, x);
}
else
{
query(rc, mid+1, r, w, x);
}
tr[d].v = min(tr[lc].v, tr[rc].v);
}
int main()
{
int h, w, n;
while(scanf("%d%d%d", &h, &w, &n) == 3)
{
for(int i = 1; i <= n; i++)
{
scanf("%d", &val[i]);
}
if(h > n) h = n;//优化
build(1, 1, h);
for(int i = 1; i <= n; i++)
{
//很妙的预先判断,把-1的情况完美处理
if(tr[1].v + val[i] > w)
{
printf("-1\n");
continue;
}
query(1, 1, h, w, val[i]);
}
}
return 0;
}