B - Vases and Flowers HDU - 4614 (線段樹+二分)

馬上就要參加湘潭邀請賽了,今天刷了一套進階的線段樹來複習複習線段樹。希望能拿到牌子~~

日常專題之進階線段樹

專題鏈接:

https://cn.vjudge.net/contest/300370#overview

A題考慮區間乘,有點難,看別人題解,光pushdown就寫了近80行代碼。先放棄了

看B題:

Vases and Flowers

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 5431    Accepted Submission(s): 2267

Problem Description

  Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N-1. When she receive some flowers, she will try to put them in the vases, one flower in one vase. She randomly choose the vase A and try to put a flower in the vase. If the there is no flower in the vase, she will put a flower in it, otherwise she skip this vase. And then she will try put in the vase A+1, A+2, ..., N-1, until there is no flower left or she has tried the vase N-1. The left flowers will be discarded. Of course, sometimes she will clean the vases. Because there are too many vases, she randomly choose to clean the vases numbered from A to B(A <= B). The flowers in the cleaned vases will be discarded.

Input

  The first line contains an integer T, indicating the number of test cases.
  For each test case, the first line contains two integers N(1 < N < 50001) and M(1 < M < 50001). N is the number of vases, and M is the operations of Alice. Each of the next M lines contains three integers. The first integer of one line is K(1 or 2). If K is 1, then two integers A and F follow. It means Alice receive F flowers and try to put a flower in the vase A first. If K is 2, then two integers A and B follow. It means the owner would like to clean the vases numbered from A to B(A <= B).

Output

  For each operation of which K is 1, output the position of the vase in which Alice put the first flower and last one, separated by a blank. If she can not put any one, then output 'Can not put any one.'. For each operation of which K is 2, output the number of discarded flowers. 
  Output one blank line after each test case.

Sample Input

2 10 5 1 3 5 2 4 5 1 1 8 2 3 6 1 8 8 10 6 1 2 5 2 3 4 1 0 8 2 2 5 1 4 4 1 2 3

Sample Output

[pre]3 7 2 1 9 4 Can not put any one. 2 6 2 0 9 4 4 5 2 3 [/pre]

題意:

有nn個花瓶,標號00 ~ n−1。mn−1。m個操作, 
1AF,表示從AA位置開始插FF朵花,遇到有花的花瓶跳過。到最後一個花瓶都還有花剩餘,丟棄剩下的花。 
2AB,表示將區間[A,B][A,B]內的花瓶全部清空。(A≤B)(A≤B) 
對於每個11操作,輸出第一個和最後一個插花的位置,如果一朵花都插不了,輸出‘Can not put any one.’;對於每個22操作,輸出區間[A,B][A,B]內被清空的花瓶的數量。

 

做法:區間保存空花瓶的數量

注意題目這裏是(0~n-1)我們建樹是1~n

對於操作2 很簡單,查詢區間A,B裏空花瓶的數量num,然後區間長度減去num就是答案。

現在來看看操作1怎麼寫 對於A,F

先看看[A,N]裏的空花瓶是否爲零,若爲零輸出 Can not put any one.

不爲零則代表可以插花

那麼將第一朵花可以插的位置通過二分區間內的空花瓶數量進行查詢位置即可。

最後一朵花可以插的位置通過二分區間內的空花瓶數量進行查詢位置即可。

最後更新一下區間內空花瓶 減少的數量

AC代碼:

#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10;
int sum[N*4],len[N*4],lazy[4*N];
int n,m,t;
void pushdown(int id)
{
	if(lazy[id]!=-1)
	{
		lazy[id<<1]=lazy[id];
		lazy[id<<1|1]=lazy[id];
		sum[id<<1]=len[id<<1]*lazy[id];
		sum[id<<1|1]=len[id<<1|1]*lazy[id];
		lazy[id]=-1;
	}
}
void build(int id,int l,int r)
{
	sum[id]=r-l+1;
	lazy[id]=-1;
	len[id]=r-l+1;
	if(l==r) return ;
	int mid=l+r>>1;
	build(id<<1,l,mid);
	build(id<<1|1,mid+1,r);
}
void up(int id,int l,int r,int ql,int qr,int val)
{
	if(ql<=l&&r<=qr)
	{
		lazy[id]=val;
		sum[id]=(r-l+1)*val;
		return ;
	}
	pushdown(id);
	int mid=l+r>>1;
	if(ql<=mid) up(id<<1,l,mid,ql,qr,val);
	if(qr>mid) up(id<<1|1,mid+1,r,ql,qr,val);
	sum[id]=sum[id<<1]+sum[id<<1|1];
}
int qu(int id,int l,int r,int ql,int qr)
{
	if(ql<=l&&r<=qr)
	{
		return sum[id];
	}
	pushdown(id);
	int mid=l+r>>1;
	int ans=0;
	if(ql<=mid) ans+=qu(id<<1,l,mid,ql,qr);
	if(qr>mid) ans+=qu(id<<1|1,mid+1,r,ql,qr);
	return ans;
}
int search(int x,int numb)
{
	int l=x,r=n,ans=-1;
	while(l<=r)
	{
		int mid=l+r>>1;
		int num=qu(1,1,n,x,mid);
		if(num>=numb) 
		{
			ans=mid;
			r=mid-1;
		}
		else l=mid+1;
	}
	return ans;
}
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		build(1,1,n);
		int cnt,l,r;
		while(m--)
		{
			scanf("%d%d%d",&cnt,&l,&r);
			if(cnt==1)
			{
				int ql,qr;
				++l;
				int num=qu(1,1,n,l,n);
				if(num==0) printf("Can not put any one.\n");
				else
				{
					ql=search(l,1);
					qr=search(l,min(num,r));
					up(1,1,n,ql,qr,0);
					printf("%d %d\n",ql-1,qr-1);
				}
			}
			else
			{
				++l,++r;
				int num=qu(1,1,n,l,r);
				printf("%d\n",r-l+1-num);
				up(1,1,n,l,r,1);
			}
		}
		puts("");
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章