【紀中2020.3.25日】模擬賽題解

目錄:

T1:公雞打鳴
T2:拯救小雞
T3:母雞下蛋
T4:雞國福利

這次的題……取名鬼才……清一色的雞

正題:

T1:公雞打鳴

題目描述

雞國中有兩隻最喜歡打鳴的公雞 G1 和 G2,它們每一次打鳴都有一個聲音的響度值。一天清晨,G1 開始先開始打鳴,響度值爲 x,G2 聽到 G1 的打鳴後也開始打鳴,響度值爲 y。G1 和 G2 很想把它們打鳴聲音的響度值調成一樣。所以它們進行了 k 次協商,每一次協商後就各自增加或減少一定的響度值再打鳴一次(打鳴的響度值不能小於 0)。G1 和 G2 生性遲鈍,它們不知道其實經過 s(s≤k)次協商後,打鳴聲音的響度值已經相同了。請編程幫 G1 和 G2 計算一下它們打鳴聲音的響度值相同時最少經過了幾次協商(即最小的 s)?
注意:如果 x 一開始就等於 y,則不需要協商。

輸入

輸入共 k+1 行。
第 1 行三個整數 x,y 和 k,分別表示 G1、G2 第一次打鳴時聲音的響度值,共進行了 k次協商並調整打鳴聲音的響度值。
接下來 k 行,每行包含 4 個整數 ai,xi,bi,yi,表示第 i 次協商 G1 增加(ai等於 1)或減少(ai等於-1)的響度值爲 xi,G2 增加(bi等於 1)或減少(bi等於-1)的響度值 yi。

輸出

輸出 1 行一個整數,表示至少經過多少次協商後 G1 和 G2 的打鳴響度值已經相同。如果經過 k 次協商後仍然無法相同,則輸出“-1”(不包含雙引號)。

樣例輸入

Input1:

2 3 3
1 1 -1 0
-1 1 1 1
1 1 -1 1

Input2:

2 3 4
1 2 -1 2
-1 1 1 1
-1 4 1 1
1 4 1 1

Input3:

2 3 1
1 2 -1 2

樣例輸出

Output1:

1

Output2:

4

Output3:

-1

分析:

這道題十分簡單。標記+累加即可。

CODE:

#include<cstdio>
#include<iostream>
using namespace std;
int main(){
	freopen("rooster.in","r",stdin);
	freopen("rooster.out","w",stdout);
	int x,y,k;
	scanf("%d%d%d",&x,&y,&k);
		int ai,xi,bi,yi;
		int count=0,flag=0,ans=0;
		if(x==y){
			printf("0\n");
			return 0;
		}
		while(k--){
			scanf("%d%d%d%d",&ai,&xi,&bi,&yi);	
			if(ai==1)
				x+=xi;
			else if(ai==-1){  //就是各種判斷+累加
				x-=xi;
				if(x<0)
				x=0;
			}
			if(bi==1)
				y+=yi;	
			else if(bi==-1){
				y-=yi;
				if(y<0)
				y=0;
			}
			count++;
			if (x==y&&!flag){
				ans=count;
				flag=1;  //用標記判斷答案合法
			}
		} 
		if(flag)
			printf("%d\n",ans);
		else
			printf("-1\n");		
	return 0;
} 

T2:拯救小雞

題目描述

雞國最近遇到了一件很棘手的事情,經常有一隻老鷹想來抓小雞。經雞國情報員探查,這隻老鷹打算共來襲擊 n 次,第 i 次來的時刻爲第 ti(1≤i≤n) 秒時刻。
雞國國王爲了保護雞國中的小雞,決定派出雞國警察(雞國有無窮多個警察)來巡邏。每個警察巡邏的時間長度都爲 t 秒。當老鷹來襲擊的時刻至少要有 x 名警察才能抵禦老鷹的襲擊。另外國王派遣警察有兩個原則:
(1)每個時刻最多隻能派遣一名警察。在第 0 秒時刻及第 0 秒之前的時刻(雞國有負數時刻)也可以事先準備派遣警察,但每個時刻最多也只能派遣一名警察。
(2)延遲 1 秒執行巡邏任務。第 i 秒時刻派遣的警察,在第 i+1 到 i+t 秒時刻執行巡邏任務。
爲幫助國王節省開支,請幫忙計算至少需要派遣多少名警察才能保證雞國小雞不被老鷹抓走?

輸入

輸入共 2 行。
第 1 行輸入三個整數n,t,x,分別表示老鷹總共襲擊次數,每個警察巡邏的時間長度,以及某個時刻能抵擋住老鷹襲擊的最少警察數量。
第 2 行 n 個嚴格升序排列的正整數 ti(1≤i≤n),表示第 ti秒時刻老鷹會發動襲擊。

輸出

輸出 1 行一個整數,表示總共至少需要派遣多少個警察才能抵禦老鷹的 n 次襲擊,如果出現無法抵禦老鷹的襲擊時,輸出“-1”(不包含雙引號)。

樣例輸入

Input1:

3 3 3
2 3 4

Input2:

1 2 3
3

樣例輸出

Output1:

5

Output2:

-1

分析:

這道題同理,也是模擬題。
過程同樣爲做標記—累加—判斷合法—輸出

CODE:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n,t,x,i,j,sum,ans,a[10001];
bool f[10001];
int main()
{
	freopen("chicken.in","r",stdin);
	freopen("chicken.out","w",stdout);
	cin>>n>>t>>x;
	for(i=1;i<=n;i++)
	cin>>a[i];
	if(x>t){
		cout<<-1;  //直接特判
		return 0;
	}
	for(i=1;i<=n;i++)
	{
		sum=0;
		for(j=a[i]-1;j>=a[i]-t;j--) if(f[j]) sum++;//從a[i]-1到a[i]-t,標記就累加
		if(sum<x)
		for(j=a[i]-1;j>=a[i]-t;j--)
		{  //重複這一過程
			f[j]=1;
			ans++;sum++;
			if(sum==x) break;
		}
	}
	cout<<ans;
	
	return 0;
}

T3:母雞下蛋

題目描述

雞國中的母雞最擅長下蛋了,MGMG 是雞國中一隻以下蛋產量高而聞名全雞國的母雞。
雞國專供下蛋的 n 個雞窩呈一字排列在雞國的“下蛋中心”,從左到右依次編號爲 1 到n。每個雞窩都有一個最大可下蛋的量,其中第 i 個雞窩的最大可下蛋量爲 ci。有時候由於MGMG 產量實在太大而無法在一個雞窩中下完所有的蛋,不得不轉移到隔壁的雞窩繼續下蛋,如果隔壁的雞窩還是不能讓它下完所有的蛋,則 MGMG 繼續轉移,直到下完所有的蛋,或者向“下蛋中心”管理員投訴“雞窩數量實在太少了,我一隻雞的下蛋量都裝不下!”。
爲了節省轉移時所耗費的體力,請你編程幫助 MGMG 找若干個連續的雞窩(個數儘量少),讓它能下完所有的蛋。

輸入

輸入共 2 行。
第 1 行輸入兩個整數 n 和 t,表示“下蛋中心”有 n 個可供下蛋的雞窩,MGMG 一次總共要下 t 個雞蛋。
第 2 行 n 個正整數 ci(1≤i≤n),依次表示第 i 個雞窩最大可下蛋量爲 ci個。

輸出

輸出 1 行一個整數或一個單詞。當輸出整數時表示讓 MGMG 下完所有的蛋至少需要幾個連續的雞窩。當 MGMG 用完所有的雞窩都無法下完所有的蛋時,MGMG 表示非常憤怒,輸出單詞“Angry”(不包含雙引號,注意大小寫)。

樣例輸入

Input1:

5 4
1 2 1 2 3

Input2:

3 9
3 3 3

Input3:

3 5
1 2 1

樣例輸出

Output1:

2

Outupt2:

3

Output3:

Angry

提示

Sample1:
樣例 1 中,有 5 個雞窩,可下蛋量分別爲 1,2,1,2,3。MGMG 如果選擇第 1,2,3號雞窩能下完 4 個蛋,但要用 3 個雞窩,而選擇第 4 號和第 5 號雞窩也能下完 4 個蛋(還有1 個多餘的容量),用到的雞窩只有 2 個。
注意:由於第 2 號和第 4 號雞窩不連續,不可以作爲選擇的方案之一。

Sample2:
樣例 2 中,有 3 個雞窩,可下蛋量分別爲 3,3,3,MGMG 可以在這 3 個連續的雞窩中每個下 3 個蛋,這樣正好總共下 9 個蛋。

Sample3:
樣例 3 中,所有雞窩的可下蛋總量小於 MGMG 的下蛋量,無法滿足 MGMG 的下蛋需求,輸出“Angry”。

分析:

這道題用單調隊列思想。也可以用前綴和做。
過程:
用一個變量存,合法的情況下ans不斷取一個最小值,和再自減
講不清楚啊看代碼……

CODE:

#include<iostream>
#include<cstdio>
using namespace std;
int m,n,ans,sum,y,a[1000001];
int main(){
	freopen("hen.in","r",stdin);
	freopen("hen.out","w",stdout);
	cin>>n>>m;
	ans=2147483647;  //用來判斷ans合法情況
	int j=1;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		sum=sum+a[i];  //累加起來存和
		y++;
		while(sum>=m){  //合法
			ans=min(y,ans);  //取最小
			sum-=a[j];  //取完就減掉這部分
			y--;  //同理
			j++; //同上可寫爲sum-=a[j++]
		}
	}
	if(ans==2147483647)cout<<"Angry"; //ans都沒變過不合法
	else cout<<ans;
	return 0;
}

T4:雞國福利

題目描述

雞國爲了表彰雞國每一隻雞在過去一年的優秀表現,打算在接下來的 n 天中每天給雞國的一隻雞發 1 袋或者 2 袋“雞幣”(雞國的通用貨幣)作爲福利。國王要求每天來領錢雞互不相同,即來領過錢的雞不能再來,否則將受到嚴厲的處罰。
但聰明的雞國老百姓偵察後發現國王每天發的錢袋子裏面裝的錢數量是不一樣的(同一天的相同),第 i 天發的每一袋錢爲 ai元。如果第 i 天來領錢的雞領 1 袋錢,它可以獲得ai元的“雞幣”,如果它領 2 袋錢,則可以獲得 2×ai元“雞幣”,當然它也可以放棄,則第i 天的錢國王收回國庫。
由於雞國生活條件優越和雞的貪念等原因,當第 i 天領錢的雞同時滿足以下兩個條件時
它纔會感到幸福:
(1)領到的錢不能低於雞國的平均收入 m 元。
(2)要跟它前面領了錢且感到幸福的雞一樣幸福或者更幸福。
仁慈的國王希望雞國的每一隻雞都能感到幸福,請你幫國王規劃一下在這 n 天中怎樣給每一隻發錢才能讓最多的雞感到幸福?

輸入

輸入共 2 行。
第 1 行輸入兩個整數 n 和 m,分別表示發錢的天數(或理解爲來領錢的雞數)和雞國的平均收入。
第 2 行 n 個正整數 ai(1≤i≤n),依次表示第 i 天發的一袋錢中的“雞幣”爲 ai元。

輸出

輸出 1 行一個整數,表示最多可以讓多少隻雞感到幸福。

樣例輸入

Input1:

2 1
2 1

Input2:

3 2
1 2 3

Input3:

6 4
1 2 1 2 1 5

樣例輸出

Output1:

2

Output2:

3

Output3:

3

提示

Sample1:
樣例 1 中,可以讓第 1 天來領錢的第 1 只雞領 2 元(1 袋),第 2 天來領錢的第 2 只雞領 2 元(2 袋),最多可以有 2 只雞感到幸福。

Sample2:
樣例 2 中,由於雞國的平均收入爲 2 元,所以領 1 元及以下的雞是不會感到幸福。可以讓第 1 天來領錢的第 1 只雞領 2 元(2 袋),第 2 天來領錢的第 2 只雞領 2 元(1 袋),第 3 天來領錢的第 3 只雞領 3 元(1 袋),最多可以有 3 只雞感到幸福。

Sample3:
樣例 3 中,由於雞國的平均收入爲 4 元,所以第 1 天,第 3 天,第 5 天來領錢的雞不管領 1 袋錢,或者領 2 袋錢,或者不領都不會感到幸福。可以讓第 2 天來領錢的第 2 只雞領4 元(2 袋),第 4 天來領錢的第 4 只雞領 4 元(2 袋),第 6 天來領錢的第 6 只雞領 5 元(1袋),最多可以有 3 只雞感到幸福。

分析:

這道題最長不下降子序列nlogn級別的。
二分然後分別做a[i]以及a[i]*2的時候做最長不下降子序列

CODE:

#include<iostream>
#include<cstdio>
using namespace std;
int m,n,len,y,a[1000010],f[1000010];
int binary(int l,int r,int g){ 
	int ans=0;
	while(l<=r){
		int mid=(l+r)/2;
		if(f[mid]>g)r=mid-1,ans=mid;
		else l=mid+1;  //二分
	}
	return ans;
}
int main(){
	freopen("kingdom.in","r",stdin);
	freopen("kingdom.out","w",stdout); 
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=n;i++){
		if(a[i]>=m){  //分別在a[i]
			if(a[i]>=f[len]){
			   	len++;
				f[len]=a[i];
	    	}
			else{
				int j=binary(1,len,a[i]);
				f[j]=a[i];
			}
		}
		if(a[i]*2>=m){  //a[i]*2的位置
			if(a[i]*2>=f[len]&&(a[i]<f[len]||i==1)){
			   	len++;
				f[len]=a[i]*2;
	    	}
			else{
				int j=binary(1,len,a[i]*2);
				f[j]=a[i]*2;
			}
		}
	}
	cout<<len; //最長上升不下降子序列
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章