线段树之HDU4614 Vases and Flowers

不敢相信自己居然1A,一气呵成。虽然写的有点丑。纪念下!

后来发现网上有二分的写法,然而跑得还不如我的快,我直接一遍扫,找pos1和pos2,二分的话每次都要跑好多次query,会慢一些,但写起来比我的简洁些。

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <sstream>
using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long LL;
const double pi=4.0*atan(1.0);
const int MAXN=100005;

int a[MAXN];
int sum[MAXN<<2];
int add[MAXN<<2];

void PushUp(int rt)
{
	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void PushDown(int rt,int len)
{
	if(add[rt]!=-1)
	{
		add[rt<<1]=add[rt];
		add[rt<<1|1]=add[rt];
		sum[rt<<1]=(1-add[rt])*(len-(len>>1));
		sum[rt<<1|1]=(1-add[rt])*(len>>1);
		add[rt]=-1;
	}
}

void build(int l,int r,int rt)
{
	add[rt]=-1;
	if(l==r)
	{
		add[rt]=0;
		sum[rt]=1;
		return ;
	}
	int m=(l+r)>>1;
	build(lson);
	build(rson);
	PushUp(rt);
}
//c 0没用 1使用 
void update(int L,int R,int c,int l,int r,int rt)
{
	if(L<=l &&r<=R)
	{
		add[rt]=c;
		sum[rt]=(1-c)*(r-l+1);
		return ;
	}
	PushDown(rt,r-l+1);
	int m=(l+r)>>1;
	
	if(L<=m)
		update(L,R,c,lson);
	if(m<R)
		update(L,R,c,rson);

	PushUp(rt);
}
int ans;
void query(int L, int R,int l,int r,int rt)
{
	if(L<=l &&r<=R)
	{
		ans+=sum[rt];
		return;
	}
	PushDown(rt,r-l+1);

	int m=(l+r)>>1;
	if(L<=m)
		query(L,R,lson);
	if(m<R)
		query(L,R,rson);
}

int pos1;
int pos2;
int s;
int sign;
int beg;
void query2(int L, int R,int l,int r,int rt)
{
	if(sign)
		return ;
	if(add[rt]!=-1)
	{
		if(add[rt]==1)
			return ;
		else 
		{
			if(L<=l &&r<=R)
			{
				if(beg==0)
				{
					pos1=l;
					beg=1;
				}
				if(s>sum[rt])
					s-=sum[rt];
				else if(s==sum[rt])
				{
					pos2=r;
					sign=1;
				}
				else
				{
					pos2=l+s-1;
					sign=1;
				}
				return;
			}
			PushDown(rt,r-l+1);

			int m=(l+r)>>1;
	
			if(L<=m)
				query2(L,R,lson);
			if(m<R)
				query2(L,R,rson);
		}
	}
	else
	{
		PushDown(rt,r-l+1);
		if(l==r)
			return ;
		int m=(l+r)>>1;
	
		if(L<=m)
			query2(L,R,lson);
		if(m<R)
			query2(L,R,rson);
	}
	
}
int main()
{
	int n,m;
	int i,j,k;
	int x,y;
	int T;
	while(scanf("%d",&T)!=EOF)
	{
		while(T--)
		{
			scanf("%d%d",&n,&m);
			build(1,n,1);
			while(m--)
			{
				scanf("%d%d%d",&k,&x,&y);
				if(k==1)
				{
					x++;
					ans=0;
					query(x,n,1,n,1);
					if(ans==0)
					{
						printf("Can not put any one.\n");
						continue;
					}
					s=min(ans,y);
					sign=0;
					beg=0;
					pos1=pos2=-1;
					query2(x,n,1,n,1);
					update(pos1,pos2,1,1,n,1);
					printf("%d %d\n",pos1-1,pos2-1);
				}
				else 
				{
					x++;
					y++;
					ans=0;
					query(x,y,1,n,1);
					printf("%d\n",y-x+1-ans);
					update(x,y,0,1,n,1);
				}
			
			}
			printf("\n");
		}
	}


	return 0;
}


二分写法

/*poj 3468*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <string>
#include <sstream>
using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

typedef long long LL;
const double pi=4.0*atan(1.0);
const int MAXN=100005;

int a[MAXN];
int sum[MAXN<<2];
int add[MAXN<<2];

void PushUp(int rt)
{
	sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void PushDown(int rt,int len)
{
	if(add[rt]!=-1)
	{
		add[rt<<1]=add[rt];
		add[rt<<1|1]=add[rt];
		sum[rt<<1]=(1-add[rt])*(len-(len>>1));
		sum[rt<<1|1]=(1-add[rt])*(len>>1);
		add[rt]=-1;
	}
}

void build(int l,int r,int rt)
{
	add[rt]=-1;
	if(l==r)
	{
		add[rt]=0;
		sum[rt]=1;
		return ;
	}
	int m=(l+r)>>1;
	build(lson);
	build(rson);
	PushUp(rt);
}
//c 0没用 1使用 
void update(int L,int R,int c,int l,int r,int rt)
{
	if(L<=l &&r<=R)
	{
		add[rt]=c;
		sum[rt]=(1-c)*(r-l+1);
		return ;
	}
	PushDown(rt,r-l+1);
	int m=(l+r)>>1;
	
	if(L<=m)
		update(L,R,c,lson);
	if(m<R)
		update(L,R,c,rson);

	PushUp(rt);
}
int ans;
void query(int L, int R,int l,int r,int rt)
{
	if(L<=l &&r<=R)
	{
		ans+=sum[rt];
		return;
	}
	PushDown(rt,r-l+1);

	int m=(l+r)>>1;
	if(L<=m)
		query(L,R,lson);
	if(m<R)
		query(L,R,rson);
}
int n;
int now;
int lower(int x,int y,int k)
{
	int m;
	while(x<y)
	{
		m=(x+y)>>1;
		ans=0;
		query(1,m,1,n,1);
		if(ans-now>=k)
			y=m;
		else
			x=m+1;
	}
	return x;
}
int main()
{
	int m;
	int i,j,k;
	int x,y;
	int T;
	while(scanf("%d",&T)!=EOF)
	{
		while(T--)
		{
			scanf("%d%d",&n,&m);
			build(1,n,1);
			while(m--)
			{
				scanf("%d%d%d",&k,&x,&y);
				if(k==1)
				{
					x++;
					ans=0;
					query(x,n,1,n,1);
					if(ans==0)
					{
						printf("Can not put any one.\n");
						continue;
					}
					y=min(ans,y);
					
					if(x==1)
					{
						now=0;
					}
					else
					{
						ans=0;
						query(1,x-1,1,n,1);
						now=ans;
					}
					
					int pos1=lower(1,n,1);
					int pos2=lower(1,n,y);
					
					update(pos1,pos2,1,1,n,1);
					printf("%d %d\n",pos1-1,pos2-1);
				}
				else 
				{
					x++;
					y++;
					ans=0;
					query(x,y,1,n,1);
					printf("%d\n",y-x+1-ans);
					update(x,y,0,1,n,1);
				}
			
			}
			printf("\n");
		}
	}


	return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值