hdu4614

/*
分析:
    就一线段树果题,配合二分,或者把对e点的查找的函数写的复杂点儿
、在里面嵌套半个logn都行。
    这是我最喜欢的几个算法之一啊!只是这段时间有点儿忙不小心冷落
了你,不要就这么狠心无情毅然决然果断地抛弃我啊!!犯了白痴错误比
赛期间愣是没有检查出来啊!!心酥了有木有啊囧~~

                                                             2013-07-26
*/








#include"iostream"
#include"cstdio"
#include"cstring"
using namespace std;
const int N=50006;

int n,m,s,e;
struct Segtree
{
	int l,r,mid;
	int len,ret,lazy;
}T[N<<2];

void build(int l,int r,int k)
{
	T[k].l=l;
	T[k].r=r;
	T[k].mid=(l+r)>>1;
	T[k].len=r-l+1;
	T[k].ret=T[k].len;
	T[k].lazy=0;
	if(l==r)	return ;
	build(l,T[k].mid,k<<1);
	build(T[k].mid+1,r,(k<<1)+1);
}
inline void push_up(int k){
	T[k].ret=T[k<<1].ret+T[(k<<1)+1].ret;
}
inline void push_down(int k)
{
	int lson=k<<1;
	int rson=lson+1;
	T[lson].lazy=T[rson].lazy=T[k].lazy;
	if(T[k].lazy==1)	T[lson].ret=T[rson].ret=0;
	else
	{
		T[lson].ret=T[lson].len;
		T[rson].ret=T[rson].len;
	}
	T[k].lazy=0;
}
int cnt(int l,int r,int k)
{
	if(T[k].l==l && T[k].r==r)	return T[k].ret;

	int ans;
	if(T[k].lazy)	push_down(k);
	if(r<=T[k].mid)		ans=cnt(l,r,k<<1);
	else if(T[k].mid<l)	ans=cnt(l,r,(k<<1)+1);
	else
	{
		ans=cnt(l,T[k].mid,k<<1);
		ans+=cnt(T[k].mid+1,r,(k<<1)+1);
	}
	push_up(k);
	return ans;
}
void find_s(int aim,int k)
{
	if(!T[k].ret)	return ;
	if(T[k].l==T[k].r)
	{
		if(T[k].l<=aim && T[k].ret)	s=T[k].l;
		return ;
	}
	if(T[k].lazy)	push_down(k);
	if(T[k].mid<aim)find_s(aim,(k<<1)+1);
	else
	{
		find_s(aim,k<<1);
		if(s==-1)	find_s(T[k].mid+1,(k<<1)+1);
	}
	push_up(k);
}
void insert(int l,int r,int k)
{
	if(T[k].l==l && T[k].r==r)
	{
		T[k].ret=0;
		T[k].lazy=1;
		return ;
	}
	if(T[k].lazy)	push_down(k);
	if(r<=T[k].mid)		insert(l,r,k<<1);
	else if(l>T[k].mid)	insert(l,r,(k<<1)+1);
	else
	{
		insert(l,T[k].mid,k<<1);
		insert(T[k].mid+1,r,(k<<1)+1);
	}
	push_up(k);
}
int clear(int l,int r,int k)
{
	int ans;
	if(T[k].l==l && T[k].r==r)
	{
		ans=T[k].len-T[k].ret;
		T[k].ret=T[k].len;
		T[k].lazy=-1;
		return ans;
	}
	if(T[k].lazy)	push_down(k);
	if(r<=T[k].mid)		ans=clear(l,r,k<<1);
	else if(l>T[k].mid)	ans=clear(l,r,(k<<1)+1);
	else
	{
		ans=clear(l,T[k].mid,k<<1);
		ans+=clear(T[k].mid+1,r,(k<<1)+1);
	}
	push_up(k);
	return ans;
}
int main()
{
	int T;
	int t,a,b,low,mid,up,temp;
	cin>>T;
	while(T--)
	{
		cin>>n>>m;
		build(0,n-1,1);
		while(m--)
		{
			scanf("%d%d%d",&t,&a,&b);
			if(t==1)
			{
				s=e=-1;
				temp=cnt(a,n-1,1);
				if(!temp)	{printf("Can not put any one.\n");continue;}
				if(temp<b)	b=temp;
				find_s(a,1);
				low=s;up=n-1;
				while(low<=up)
				{
					mid=(low+up)>>1;
					temp=cnt(a,mid,1);
					if(temp<b)	low=mid+1;
					else	up=mid-1;
				}
				e=low;
				insert(s,e,1);
				printf("%d %d\n",s,e);
			}
			else	printf("%d\n",clear(a,b,1));
		}
		cout<<endl;
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值