二分+線段樹 [USACO17JAN]Cow Dance Show S(洛谷 P3611)

[USACO17JAN]Cow Dance Show S

題目描述

After several months of rehearsal, the cows are just about ready to put on their annual dance performance; this year they are performing the famous bovine ballet “Cowpelia”.

The only aspect of the show that remains to be determined is the size of the stage. A stage of size KK can support KK cows dancing simultaneously. The NN cows in the herd (1 \leq N \leq 10,0001≤N≤10,000) are conveniently numbered 1 \ldots N1…N in the order in which they must appear in the dance. Each cow ii plans to dance for a specific duration of time d(i)d(i). Initially, cows 1 \ldots K1…K appear on stage and start dancing. When the first of these cows completes her part, she leaves the stage and cow K+1K+1 immediately starts dancing, and so on, so there are always KK cows dancing (until the end of the show, when we start to run out of cows). The show ends when the last cow completes her dancing part, at time TT.

Clearly, the larger the value of KK, the smaller the value of TT. Since the show cannot last too long, you are given as input an upper bound T_{max}T
max

specifying the largest possible value of TT. Subject to this constraint, please determine the smallest possible value of KK.

經過幾個月的排練,奶牛們基本準備好展出她們的年度舞蹈表演。今年她們要表演的是著名的奶牛芭蕾——“cowpelia”。

表演唯一有待決定的是舞臺的尺寸。一個大小爲K的舞臺可以支持K頭牛同時在舞臺上跳舞。在牛羣中的N頭牛(1<=N<=10,000)按照她們必須出現在舞蹈中的順序方便地編號爲1…N。第i頭牛計劃跳d[i]的特定持續時間。一開始,第1…K頭牛出現在舞臺上並開始跳舞。當這些牛中的某一頭牛首先完成了她的部分,她會馬上離開舞臺並且第K+1頭牛會出現在舞臺上並開始跳舞。所以,舞臺上總有K頭奶牛在跳舞(直到表演的尾聲,奶牛不夠的時候)。當最後一頭奶牛完成了她的舞蹈部分,表演結束,共花了T個單位時間。

顯然,K的值越大,T就越小。由於表演不能拖太長,你得知了指定T的最大可能值的上限T-max。請根據這個約束,確定K的最小值。

輸入格式

The first line of input contains NN and T_{max}T
max

, where T_{max}T
max

is an integer of value at most 1 million.

The next NN lines give the durations d(1) \ldots d(N)d(1)…d(N) of the dancing parts for cows 1 \ldots N1…N. Each d(i)d(i) value is an integer in the range 1 \ldots 100,0001…100,000.

It is guaranteed that if K=NK=N, the show will finish in time.

第一行包括N和T-max兩個整數(T-max<=1,000,000)。

接下來的N行給出了第1…n頭牛跳舞的持續時間d[1]…d[n]。第i行包括一個整數d[i],1<=d[i]<=100,000.

保證K=N時表演會按時完成。

輸出格式

Print out the smallest possible value of KK such that the dance performance will take no more than T_{max}T
max

units of time.

輸出在表演時間不大於T-max時的K的最小可能值。


二分 K 很明顯,就是這個線段樹寫起來比較麻煩;

首先知道是維護區間最大,最小值,每次取區間最小值,然後減去區間最小值,當到達最後一個的時候,直接加上區間最大值,因爲這個時候沒有奶牛入隊了;

代碼:

#include<bits/stdc++.h>
#define LL long long
#define pa pair<int,int>
#define ls k<<1
#define rs k<<1|1
#define inf 0x3f3f3f3f
using namespace std;
const int N=10100;
const int M=2000100;
const int mod=1e9;
int n,m,d[N];
struct Node{
	int l,r,mmin,mmax,pos,f;
}tr[N*4];
void pp(int k){
	if(tr[ls].mmin<=tr[rs].mmin) tr[k].mmin=tr[ls].mmin,tr[k].pos=tr[ls].pos;
	else tr[k].mmin=tr[rs].mmin,tr[k].pos=tr[rs].pos;
	tr[k].mmax=max(tr[ls].mmax,tr[rs].mmax);
}
void pd(int k){
	if(tr[k].f){
		tr[ls].mmax-=tr[k].f,tr[rs].mmax-=tr[k].f;
		tr[ls].mmin-=tr[k].f,tr[rs].mmin-=tr[k].f;
		tr[ls].f+=tr[k].f,tr[rs].f+=tr[k].f;
	}
	tr[k].f=0;
}
void build(int l,int r,int k){
	tr[k].l=l,tr[k].r=r,tr[k].f=0;
	if(l==r){
		tr[k].mmin=d[l],tr[k].mmax=d[l],tr[k].pos=l;
		return;
	}
	int d=(l+r)>>1;
	build(l,d,ls);
	build(d+1,r,rs);
	pp(k);
}
void add(int pos,int w,int k){
	if(tr[k].l==tr[k].r){
		tr[k].mmin=w,tr[k].mmax=w;
		return;
	}
	pd(k);
	int d=(tr[k].l+tr[k].r)>>1;
	if(pos<=d) add(pos,w,ls);
	else add(pos,w,rs);
	pp(k);	
}
void update(int w,int k){
	tr[k].mmax-=w,tr[k].mmin-=w;
	tr[k].f+=w;
} 
bool judge(int p){
	LL ans=0;
	build(1,p,1);
	if(p==n) ans+=tr[1].mmax;
	else ans+=tr[1].mmin;
	for(int i=p+1;i<=n;i++){
		update(tr[1].mmin,1);
		add(tr[1].pos,d[i],1);
		if(i==n) ans+=tr[1].mmax;
		else ans+=tr[1].mmin;
	}
	if(ans<=1ll*m) return true;
	return false;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&d[i]);
	int l=1,r=n,ans=0;
	while(l<=r){
		int d=(l+r)>>1;
		if(judge(d)){
			ans=d;
			r=d-1;
		}
		else l=d+1;
	}
	printf("%d\n",ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章