HDU - 4614

比较简单,一发A。

这几个操作很明显线段树维护。

初是区间都是0,代表某个区间花数量和

2 a b 把区间赋值成0,查询区间和。

1 a f 查询  a - n-1 区间无花数量是否小于f  小于的花直接全部插上花,插之前询问最左边无花,最右边无花的瓶子位置即最小值最右边//最左 的坐标。

如果区间无花数量大于f。则二分查找区间无花数量第一个大于等于f的位置。刚好这个区间插满花,右边为pos左边为区间最左边无花位置。

//KX
#include 
using namespace std;
typedef long long ll;
typedef double db;
const int M = 5e4+7;
#define ls o*2
#define rs o*2+1
#define pb push_back
int st[M<<2],tag[M<<2],mn[M<<2];
void pd(int o,int l,int r)
{
	if(tag[o]==-1)return ;
	int m=(l+r)/2;
	mn[ls]=mn[rs]=tag[ls]=tag[rs]=tag[o];
	st[ls]=tag[o]*(m-l+1);
	st[rs]=tag[o]*(r-m);
	tag[o]=-1;
	return ;
}
void bd(int o,int l,int r)
{
	mn[o]=st[o]=0,tag[o]=-1;
	if(l==r)
	{
		return ;
	}
	int m=(l+r)/2;
	bd(ls,l,m);
	bd(rs,m+1,r);
}
void up(int o,int l,int r,int x,int y,int d)//区间覆盖 
{
//	printf("%d   %d   %d   %d\n",l,r,x,y);
	if(x<=l&&r<=y)
	{
		mn[o]=d;
		st[o]=d*(r-l+1);
		tag[o]=d;
		return ;
	}
	pd(o,l,r);
	int m=(l+r)/2;
	if(x<=m)up(ls,l,m,x,y,d);
	if(y>m)up(rs,m+1,r,x,y,d);
	mn[o]=min(mn[ls],mn[rs]);
	st[o]=st[ls]+st[rs];
}
int qu(int o,int l,int r,int x,int y)//区间和
{
	if(x<=l&&r<=y)
	{
		return st[o];
	}
	pd(o,l,r);
	int m=(l+r)/2;
	int ans=0;
	if(x<=m)ans+=qu(ls,l,m,x,y);
	if(y>m)ans+=qu(rs,m+1,r,x,y);
	return ans;
}
bool fl;
int ps;
void qul(int o,int l,int r,int x,int y)//区间最小值  最左边 
{
//	printf("%d  %d  %d    %d %d\n",l,r,mn[o],x,y);
	if(l>y||ry||r=b)//第一个大于等于b 
					{
						pos=mid;
						r=mid-1;
					}
					else
						l=mid+1;
				}
			//	puts("zzzz");
				up(1,1,n,pl,pos,1);
				printf("%d %d\n",pl-1,pos-1);
			}
			else
			{
				b++;
				int w=qu(1,1,n,a,b);
				up(1,1,n,a,b,0);
				printf("%d\n",w);
			}
			
		}
		puts("");
	 } 
  	return 0;
}

看了网上别人的解法,写了一个纯二分的。这种线段树处理比较简单

只有区间更新,区间赋值。

二分查找第一个无花数量大于1即左边插花位置,第一个无花数量大于要插的花,即右边插花位置

//KX
#include 
using namespace std;
typedef long long ll;
typedef double db;
const int M = 5e4+7;
#define ls o*2
#define rs o*2+1
#define pb push_back
int st[M<<2],tag[M<<2],mn[M<<2];
void pd(int o,int l,int r)
{
	if(tag[o]==-1)return ;
	int m=(l+r)/2;
	mn[ls]=mn[rs]=tag[ls]=tag[rs]=tag[o];
	st[ls]=tag[o]*(m-l+1);
	st[rs]=tag[o]*(r-m);
	tag[o]=-1;
	return ;
}
void bd(int o,int l,int r)
{
	mn[o]=st[o]=0,tag[o]=-1;
	if(l==r)
	{
		return ;
	}
	int m=(l+r)/2;
	bd(ls,l,m);
	bd(rs,m+1,r);
}
void up(int o,int l,int r,int x,int y,int d)//区间覆盖 
{
//	printf("%d   %d   %d   %d\n",l,r,x,y);
	if(x<=l&&r<=y)
	{
		mn[o]=d;
		st[o]=d*(r-l+1);
		tag[o]=d;
		return ;
	}
	pd(o,l,r);
	int m=(l+r)/2;
	if(x<=m)up(ls,l,m,x,y,d);
	if(y>m)up(rs,m+1,r,x,y,d);
	mn[o]=min(mn[ls],mn[rs]);
	st[o]=st[ls]+st[rs];
}
int qu(int o,int l,int r,int x,int y)//区间和
{
	if(x<=l&&r<=y)
	{
		return st[o];
	}
	pd(o,l,r);
	int m=(l+r)/2;
	int ans=0;
	if(x<=m)ans+=qu(ls,l,m,x,y);
	if(y>m)ans+=qu(rs,m+1,r,x,y);
	return ans;
}
int main()
{
	int t,n,q,k,a,b;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&q);
		bd(1,1,n);
		while(q--)
		{
			scanf("%d%d%d",&k,&a,&b);
			/*for(int i=1;i<=n;i++)
			printf("%d   ",qu(1,1,n,i,i));
			puts("ok");*/
			a++;
			if(k==1)
			{
				int w=qu(1,1,n,a,n);
				//printf("---  %d\n",w);
				w=n-a+1-w;
				if(w==0)
				{
					puts("Can not put any one.");
					continue;
				}
				if(w=1)//第一个大于等于1 
					{
						pl=mid;
						r=mid-1;
					}
					else
						l=mid+1;
				}
				
				l=pl,r=n;
				int pos=n;
				while(l<=r)
				{
					int mid=(l+r)/2;
					w=qu(1,1,n,pl,mid);//有花的个数 
					w=mid-pl+1-w;//无花的个数 
					if(w>=b)//第一个大于等于b 
					{
						pos=mid;
						r=mid-1;
					}
					else
						l=mid+1;
				}
			//	puts("zzzz");
				up(1,1,n,pl,pos,1);
				printf("%d %d\n",pl-1,pos-1);
			}
			else
			{
				b++;
				int w=qu(1,1,n,a,b);
				up(1,1,n,a,b,0);
				printf("%d\n",w);
			}
			
		}
		puts("");
	 } 
  	return 0;
}

 

你可能感兴趣的:(HDU - 4614)