hdu 2795 Billboard

刚开始咋想也想不通10^9啊,肿么用线段树啊啊啊。

后来忍不住看人家的,才明白了。额。。。因为n最大为20W啊,只要开min(h,n)即可了。因为最多也就用n行。

这么一来就很好写了。线段树最后一层存的是每行的剩余量,然后父节点存当前子树中最大连续空余。然后类似二分查找即可。

#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")

using namespace std;

const int MAX = 200010;
struct Tnode{int l,r,val;};
Tnode node[MAX << 2];
int w;
void init()
{
	memset(node,0,sizeof(node));
}
void Build(int t,int l,int r)
{
	node[t].l = l; node[t].r = r;
	if( node[t].l == node[t].r - 1 )
	{
		node[t].val = w;
		return ;
	}
	int mid = MID(l,r);
	Build(L(t),l,mid);
	Build(R(t),mid,r);
	node[t].val = max(node[L(t)].val,node[R(t)].val);
}

int Updata(int t,int l,int r,int val)
{
	if( node[t].val < val )  return -1;
	if( node[t].l == node[t].r - 1 && node[t].val >= val )
	{
		node[t].val -= val;
		return node[t].r;
	}
	int mid = MID(node[t].l,node[t].r);
	int ans = -1;
	if( val <= node[L(t)].val )
		ans = Updata(L(t),l,r,val);
	else
		if( val <= node[R(t)].val )
			ans = Updata(R(t),l,r,val);
	node[t].val = max(node[L(t)].val,node[R(t)].val);	
	return ans;
}

int main()
{
	int h,n,d;

	while( ~scanf("%d%d%d",&h,&w,&n) )
	{
		Build(1,0,min(h,n));
		for(int i=0; i<n; i++)
		{
			scanf("%d",&d);
			int ans = Updata(1,0,n,d);
			printf("%d\n",ans);
		}
	}
return 0;
}


你可能感兴趣的:(struct,Build)