线段树 hdu4614

  二分细节注意

 #include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+5; 
int n,m,a[maxn];
//花瓶里有花就不能插.一个花瓶只能有一朵花. 所以val不存花瓶里的花数 
struct tt{
	int lazy;//初始为-1,全空为1,全满为0 
	int val;//存空花瓶数 !! 
}t[maxn<<2];
void pushup(int rt){
	t[rt].val=t[rt<<1].val+t[rt<<1|1].val;
}
void build(int rt,int l,int r){
	t[rt].lazy=-1;
	t[rt].val=r-l+1;//存rt的整个区间的空花瓶数 
	if(l==r) return;//若val只在叶节点赋值则写在if里 
	int mid=(l+r)>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	pushup(rt);
}
void pushdown(int rt,int ln,int rn){
	if(t[rt].lazy!=-1){
		t[rt<<1].lazy=t[rt].lazy;
		t[rt<<1|1].lazy=t[rt].lazy;
		t[rt<<1].val=t[rt].lazy*ln;
		t[rt<<1|1].val=t[rt].lazy*rn;
		t[rt].lazy=-1;
	}
} 
//z=0时:lazy=0全满,val=0空花瓶数为0 
void update(int L,int R,int z,int rt,int l,int r){
	if(R<l||L>r) return;
	if(L<=l&&r<=R){
		t[rt].val=z*(r-l+1);
		t[rt].lazy=z;		
		return;
	}
	//if(l==r) return; 
	int mid=(l+r)>>1;
	pushdown(rt,mid-l+1,r-mid);
	if(L<=mid) update(L,R,z,rt<<1,l,mid);
	if(R>mid) update(L,R,z,rt<<1|1,mid+1,r);
	pushup(rt);
}
int que(int L,int R,int rt,int l,int r){
	if(L>r||R<l) return 0;
	if(L<=l&&r<=R) 
		return t[rt].val;
	int ans=0;
	int mid=(l+r)>>1;
	pushdown(rt,mid-l+1,r-mid);
	ans+=(que(L,R,rt<<1,l,mid)+que(L,R,rt<<1|1,mid+1,r));
	return ans;
}
int bs(int x,int num){
	int l=x,r=n;
	int mid,ans=0;
	while(l<=r){
		mid=(l+r)>>1;
		//不能一等于就break,因为可能1-3区间有两个,但第三个不是,所以1-2也是两个,所以取2。所以还要让r变小让他走下去 
//		if(que(x,mid,1,1,n)==num) ans=mid,r=mid-1;//位置等于右端值	
//		if(que(x,mid,1,1,n)>num) r=mid-1;    //错误
		if(que(x,mid,1,1,n)>=num) ans=mid,r=mid-1;
        //是x不是l!!所以开始时得定义l=x ,不能改变x,因为永远要从x开始 
		else l=mid+1;
	}
	return ans;
}
int main(){
	int T,x,y,z;
	cin>>T;
	while(T--){
		cin>>n>>m;
		build(1,1,n); 
		while(m--){
			scanf("%d%d%d",&x,&y,&z);
			if(x==1){
				y++;//花瓶 编号从0开始。所以输出的时候也要减去 
				int cnt=que(y,n,1,1,n);
				if(!cnt) 
					printf("Can not put any one.\n");
				else{
					int L=bs(y,1);//从y开始找第1个花瓶为空的位置 
					int R=bs(y,min(cnt,z));//找最后一个 
				 	update(L,R,0,1,1,n);
				 	printf("%d %d\n",L-1,R-1); 
				}
			} 
			else {
				//这个区间最多有这么多花,减去空花瓶即没花的数量,就是这个区间的花的数量 
				y++;z++; 
				printf("%d\n",z-y+1-que(y,z,1,1,n));
				update(y,z,1,1,1,n);
			}
		}
		puts("");
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值