CF-Educational 76 A,B,C,D,E

Contest:https://codeforces.com/contest/1257

目錄

A-Two Rival Students(暴力)

B- Magic Stick(規律)

C-Dominated Subarray(暴力)

D-Yet Another Monster Killing Problem(思維+暴力)

E-The Contest(思維+DP)


A-Two Rival Students(暴力)

題目鏈接:https://codeforces.com/contest/1257/problem/A

題目大意:n個人,可以調換x次,兩個對手分別在位置a和b處,問最遠能夠讓對手距離多遠,每次換位置只能和身邊的人交換。

思路:最左邊的向左移動,最右邊的向右移動,直到沒有機會爲止。

ACCode:

int main(){
	int T;scanf("%d",&T);
	while(T--){
		int n,x,a,b;scanf("%d%d%d%d",&n,&x,&a,&b);
		if(a>b) swap(a,b);
		for(x;x>=1&&a>=2;--x) --a;
		for(x;x>=1&&b<=n-1;--x) ++b;
		printf("%d\n",b-a);
	}
	
}

B- Magic Stick(規律)

題目鏈接:https://codeforces.com/contest/1257/problem/B

題目大意:給出x和y。x有兩種操作:1.當且僅當x%2==0時,x=x*3/2。2.x=x-1;可以進行無限次操作,問x是否能變成y。

思路:首先容易發現,x=2時只能變成3,2,1。x=3時只能變成3,2,1。x=4時就是無限了。特判一下就好了。

ACCode:

int main(){
	int T;scanf("%d",&T);
	while(T--){
		ll x,y;scanf("%lld%lld",&x,&y);
		if(x>=y){
			printf("YES\n");continue ;
		}
		if(x==1||x==3){
			printf("NO\n");continue ;
		}
		if(x==2&&y>3){
			printf("NO\n");continue ;
		}
		printf("YES\n"); 
	}
	
}

C-Dominated Subarray(暴力)

題目鏈接:https://codeforces.com/contest/1257/problem/C

題目大意:給出n個元素的數組A。A的支配元素就是A中數量最多的元素。一個數組的支配元素只能有1個。現在求數組A的連續子數組,問最短的有支配元素的子數組的長度。

思路:很容易發現,找到最近的兩個相同的元素就好了。

ACCode:

int A[MAXN],Cnt[MAXN],Pre[MAXN];
int n;
 
int main(){
	int Cas;scanf("%d",&Cas);
	while(Cas--){
		scanf("%d",&n);
		for(int i=1;i<=n;++i) Cnt[i]=0;
		for(int i=1;i<=n;++i) scanf("%d",&A[i]);
		for(int i=1;i<=n;++i) Cnt[A[i]]++;
		int maxcnt=0;
		for(int i=1;i<=n;++i) maxcnt=max(maxcnt,Cnt[i]);//得到支配值的數量 
		if(maxcnt==1||n==1){
			printf("-1\n");continue ;
		}
		for(int i=1;i<=n;++i) Cnt[i]=0,Pre[i]=-1;
		int ans=n;
		for(int i=1;i<=n;++i){
			Cnt[A[i]]++;
			if(Cnt[A[i]]==1){
				Pre[A[i]]=i;
			}
			else{
				ans=min(ans,i-Pre[A[i]]+1);
				Pre[A[i]]=i;
			}
		}printf("%d\n",ans);
	}
	
}

D-Yet Another Monster Killing Problem(思維+暴力)

題目鏈接:https://codeforces.com/contest/1257/problem/D

題目大意:給出n個怪物的防禦。m個英雄的攻擊p和耐力s。如果英雄的攻擊<怪物的防禦,沒有傷害,否則會直接秒殺怪物。英雄一次可以連續攻擊s下。問最後按順序消滅所有怪物,最少多少次英雄。同一個英雄可以使用多次。

思路:我們對耐力進行處理。Atk[i]表示耐力爲i的情況最高攻擊力是多少。這樣就可以枚舉怪物了。對於一次攻擊。枚舉耐力。找到最大的耐力滿足Atk[i]>=Hp[j]。就可以直接求出了。

ACCode:

int Atk[MAXN];
int Hp[MAXN];
int n,m;
 
int main(){
	int T;scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		for(int i=1;i<=n;++i) Atk[i]=0;
		for(int i=1;i<=n;++i) scanf("%d",&Hp[i]);
		scanf("%d",&m);
		for(int i=1;i<=m;++i){
			int p,s;scanf("%d%d",&p,&s);
			if(Atk[s]<p) Atk[s]=p;//耐久爲s的最高攻擊力 
		}
		for(int i=n-1;i>=1;--i){
			Atk[i]=max(Atk[i],Atk[i+1]);
		}
		int flag=1,ans=0;
		for(int pos=1,j;pos<=n;pos=j){
			int maxhp=Hp[pos];
			if(maxhp>Atk[1]){//該點總是過不去 
				flag=0;break;
			}
			for(j=pos;j<=n;++j){//最遠能走多遠 
				maxhp=max(maxhp,Hp[j]);//最大血量 
				if(Atk[j-pos+1]>=maxhp) continue ;//可以打這麼多下 
				//打不了這麼多下 
				break;
			}ans++;
		}
		if(flag) printf("%d\n",ans);
		else printf("-1\n");
	}
	
}

E-The Contest(思維+DP)

題目鏈接:https://codeforces.com/contest/1257/problem/E

題目大意:給出三個人,一開始每個人有手頭都有ki個任務,然後給出每個人的手頭任務。但是,第一個人只完成連續的前n個。第二個人只完成連續的中間的。第三個人只完成連續的最後面的。問這些人需要將任務最少交換多少次才能滿足每個人的需求。

思路:注意有些人可以不完成任務,有些人可以完成所有的任務。先將每個人的任務排一下序

枚舉第一個人完成的任務個數,[0,i]。記錄一下要完成i個任務,需要丟棄多少任務Cnt1[i].

枚舉第三個人完成的任務個數,[i,n+1]。記錄一下要完成i個任務,需要丟棄的任務數量Cnt[i];

對於第二個人。我們容易發現:

當他要完成[l,n]個任務的時候。丟棄所有前面的任務Cntl2[l],必定丟棄到第一個人。而第一個人丟棄的任務必定給了第二個人,因此,可以得到,第一個人完成l個任務的時候,操作數爲Cnt1[l]+Cntl2[l];這時,第三個人一直是沒有任務的。

當他要完成[1,r]個任務的時候,丟棄後面的任務Cntr2[r]必定丟棄給第三個人。而第三個人必定丟棄給第二個人。因此同理可以得到:第三個人完成r個任務的時候,操作數爲Cnt3[r]+Cntr2[r];。這時,第一個人是一直沒有任務的。

最後,枚舉第一個人的任務數l。找到最小的操作數r加和,維護一下最小值即可。

ACCode:

#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<time.h>
#include<math.h>
// srand((unsigned)time(NULL));rand();
      
#include<map>//unordered_map
#include<set>//multiset
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
 
#define ll long long
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define clean(a,b) memset(a,b,sizeof(a))
using namespace std;
      
const int MAXN=2e5+10;
//const int MAXM=10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
//unsigned register
// ios::sync_with_stdio(false)

int A[MAXN],B[MAXN],C[MAXN];
int Out1[MAXN],Out3[MAXN];
int Optl2[MAXN],Optr2[MAXN];
int n,k1,k2,k3;

int main(){
	while(~scanf("%d%d%d",&k1,&k2,&k3)){
		n=k1+k2+k3;
		for(int i=1;i<=k1;++i) scanf("%d",&A[i]);
		for(int i=1;i<=k2;++i) scanf("%d",&B[i]);
		for(int i=1;i<=k3;++i) scanf("%d",&C[i]);
		sort(A+1,A+1+k1);sort(B+1,B+1+k2);sort(C+1,C+1+k3);
		int cnt=k1;
		for(int i=0,j=1;i<=n;++i){//第一個人:[0,i]任務 
			while(j<=k1&&A[j]<=i) ++j,--cnt;
			Out1[i]=cnt;
		}
		cnt=k3;
		for(int i=n+1,j=k3;i>=1;--i){//第三個人:[i,n+1]任務 
			while(j>=1&&C[j]>=i) --j,--cnt;
			Out3[i]=cnt;
		}
//		for(int i=0;i<=n;++i) printf("%d ",Out1[i]);puts("");
//		for(int i=1;i<=n+1;++i) printf("%d ",Out3[i]);puts("");
		cnt=0;
		for(int i=1,j=1;i<=n;++i){//第二個人:[i,n] 凡是小於的都踢出去 
			while(j<=k2&&B[j]<i) ++j,++cnt;
			Optl2[i]=cnt+Out1[i];
		}
		cnt=0;
		for(int i=n,j=k2;i>=1;--i){//第二個人:[1,i] 凡是大於的都踢出去 
			while(j>=1&&B[j]>i) --j,++cnt;
			Optr2[i]=cnt+Out3[i];
		}
//		printf("mid l:");for(int i=1;i<=n;++i) printf("%d ",Optl2[i]);puts("");
//		printf("mid r:");for(int i=1;i<=n;++i) printf("%d ",Optr2[i]);puts("");
		for(int i=n-1;i>=1;--i){
			Optr2[i]=min(Optr2[i],Optr2[i+1]);
		}
		int ans=INF32;
		for(int i=1;i<=n;++i){
			ans=min(ans,Optl2[i]+Optr2[i]);
//			printf("ans=%d\n",ans);
		}printf("%d\n",ans);
	}
}

 

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