现在的位置: 首页 > 综合 > 正文

hdu 4614 Vases and Flowers 线段树

2019年02月20日 ⁄ 综合 ⁄ 共 2568字 ⁄ 字号 评论关闭

题意:n个点m次操作,1:从st处开始向右找出最多的0,使0变1 。2:使连续一段区间的1都变0

主要是区间更新及区间查询,更新就是找出区间记录下来的x就行了,查询的时候由于查找的区间是不连续的,因此需要根据区间内1的数量,确定更新的起点和终点,然后普通的成端更新就可以了

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 50050;

struct node{
	int l, r;
	int len, x, add;
}tr[N << 2];
//x 剩下的位置来插花
//add = 1表示有插花,0表示没处理,-1表示清理过
//所以在pushdown的时候,没处理过或者重新清理过的x都为len,有插花x则为0
int n, m;
int st, ed;

void build( int l, int r, int rt )
{
	tr[rt].l = l;
	tr[rt].r = r;
	tr[rt].add = 0;
	tr[rt].len = ( r - l + 1);
	tr[rt].x = tr[rt].len;
	if( l == r )
		return;
	int mid = ( l + r ) >> 1;
	build( lson );
	build( rson );
}

void pushup( int rt )
{
	tr[rt].x = tr[rt<<1].x + tr[rt<<1|1].x;
}

void down( int rt )
{
	tr[rt<<1|1].add = tr[rt<<1].add = tr[rt].add;
	if( tr[rt].add == -1 || tr[rt].add == 0 )
	{
		tr[rt<<1].x = tr[rt<<1].len;
		tr[rt<<1|1].x = tr[rt<<1|1].len;
	}
	else
		tr[rt<<1].x = tr[rt<<1|1].x = 0;
	tr[rt].add = 0;
}

void find_st( int aim, int rt )
{
	if( !tr[rt].x )
		return;
	if( tr[rt].l == tr[rt].r )
	{
		if( tr[rt].l <= aim && tr[rt].x )
			st = tr[rt].l;
		return;
	}
	if( tr[rt].add )
		down( rt );
	int mid = ( tr[rt].l + tr[rt].r ) >> 1;
	if( aim > mid )
		find_st( aim, rt << 1 | 1);
	else
	{
		find_st( aim, rt << 1 );
		if( st == -1 )
			find_st( mid+1, rt << 1 | 1 );
	}
	pushup( rt );
}

int query( int l, int r, int rt )	//计算区间内空花盆数量
{
	if( l <= tr[rt].l && tr[rt].r <= r )
	{
		return tr[rt].x;
	}
	if( tr[rt].add )
		down( rt );
	int mid = ( tr[rt].l + tr[rt].r ) >> 1, ans;
	if( r <= mid )
		ans = query( l, r, rt << 1 );
	else if( l > mid )
		ans = query( l, r, rt << 1 | 1 );
	else
		ans = query( lson ) + query( rson );
	pushup( rt );
	return ans;
}

void insert( int l, int r, int rt )	//插入花
{
	if( l <= tr[rt].l && tr[rt].r <= r )
	{
		tr[rt].add = 1;
		tr[rt].x = 0;
		return;
	}
	if( tr[rt].add )
		down( rt );
	int mid = ( tr[rt].l + tr[rt].r ) >> 1;
	if( r <= mid )
	{
		insert( l, r, rt << 1 );
	}
	else if( l > mid )
	{
		insert( l, r, rt << 1 | 1 );
	}
	else
	{
		insert( lson );
		insert( rson );
	}
	pushup( rt );
}

int update( int l, int r, int rt )	//清理
{
	int ans;
	if( l <= tr[rt].l && tr[rt].r <= r )
	{
		tr[rt].add = -1;
		ans = tr[rt].len - tr[rt].x;
		tr[rt].x = tr[rt].len;
		return ans;
	}
	if( tr[rt].add )
		down( rt );
	int mid = ( tr[rt].l + tr[rt].r ) >> 1;
	if( r <= mid )
		ans = update( l, r, rt << 1 );
	else if( l > mid )
		ans = update( l, r, rt << 1 | 1 );
	else
		ans = update( lson ) + update( rson );
	pushup( rt );
	return ans;
}

int main()
{
	int tot;
	scanf("%d", &tot);
	while( tot-- )
	{
		scanf("%d%d", &n, &m);
		int op, s, cnt;
		build( 0, n-1, 1 );
		while( m-- )
		{
			scanf("%d%d%d", &op, &s, &cnt);
			if( op == 1 )
			{
				st = ed = -1;
				int cur = query( s, n-1, 1 );
				if( cur == 0 )
				{
					puts("Can not put any one.");
					continue;
				}
				if( cur < cnt )
					cnt = cur;
				find_st( s, 1 );	//第一个位置
				int l = s, r = n-1;
				//二分确定区间最后一个位置
				while( l <= r )
				{
					int mid = ( l + r ) >> 1;
					if( query( s, mid, 1 ) < cnt )
						l = mid + 1;
					else
						r = mid - 1;
				}
				ed = l;
				insert( st, ed, 1 );
				printf("%d %d\n", st, ed );
			}
			else
			{
				printf("%d\n", update( s, cnt, 1 ));
			}
		}
		puts("");
	}
	return 0;
}

抱歉!评论已关闭.