Codeforces Round 983 (Div. 2) 題解

Persona_owl發表於2024-11-02

Codeforces Round 983 (Div. 2) 題解

Codeforces Round 983 (Div. 2)

Problem - A - Codeforces

解題思路

  • 考慮貪心,每個燈連兩個開關,即兩個開的燈可以關閉一盞燈,則燈數最多則儘可能讓兩個開關都開的燈儘量少,燈數最少則反之
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
int a[110];
void solve(){
	int n;cin>>n;
	int cnt0=0,cnt1=0;
	for(int i=1;i<=2*n;i++){
		int x;cin>>x;
		if(x==1) cnt1++;
		else cnt0++;
	}
	int ans1=0,ans2=0;
	if(cnt1<=n) ans1=cnt1;
	else ans1=n-(cnt1-n);
	ans2=cnt1%2;
	cout<<ans2<<" "<<ans1<<endl;
}
int main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T;cin>>T;
	while(T--) solve();
	return 0;
}

Problem - B - Codeforces

解題思路

  • 構造,我們可以考慮這樣一個構造,將陣列分成三段,第k個數為中間一段,並且令k為中位數,這樣的話,加上前後的陣列則滿足題目意思
  • 注意特判n=1時直接輸出1,k=1或k=n時輸出-1
  • k要分奇偶討論,如果k為偶數則[1,k-1],[k,k],[k+1,n];如果k為奇數則[1,k-2],[k-1,k+1],[k+2,n]
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N=2e5+10;
int a[N];
void solve(){
	int n,k;cin>>n>>k;
	if(n==1){
		cout<<1<<endl;
		cout<<1<<endl;
		return;
	}
	if(k==1 || k==n){
		cout<<-1<<endl;
		return;
	}
	if(k%2==0){
		cout<<3<<endl;
		cout<<1<<" "<<k<<" "<<k+1<<endl;
	}
	else{
		cout<<3<<endl;
		cout<<1<<" "<<k-1<<" "<<k+2<<endl;
		return;
	}
}
int main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T;cin>>T;
	while(T--) solve();
	return 0;
}

Problem - C - Codeforces

解題思路

  • 要滿足a[i]+a[j]>a[k],那麼假如我們讓最小的兩個值相加能大於陣列裡的最大值,則一定可以滿足,不妨排序一下,我們二分第一個大於a[1]+a[2]的位置id,則我們只需更改n-id+1個數則可以滿足題意
  • 但上述不一定是最少的操作次數,因為我們也可以透過更改a[1]或者a[2]使得滿足題意思,如果我們更改a[1],a[2]的值,我們一定能讓其中一個數與其他數的和都能滿足題意
  • 所以我們可以將題意簡化成,我們每次刪除一個數字,使得所有的a[i]+a[j]>a[k],(因為我們最多對一個數操作一次賦值,並且他與其他數的和一定滿足題意)
  • 所以列舉a[i],二分第一個大於a[i]+a[i+1]的位置id,ans即為(i-1)+(n-id+1)
  • 時間複雜度為O(nlogn)
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int N=2e5+10;
int a[N];
void solve(){
	int n;cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+n+1);
	int ans=1e9;
	for(int i=1;i<=n-1;i++){
		int x=a[i]+a[i+1];
		int id=lower_bound(a+1,a+n+1,x)-a;
		int tmp=n-id+1+i-1;
	//	cout<<x<<" "<<id<<" "<<tmp<<endl;
		ans=min(ans,tmp);
	}
	cout<<ans<<endl;
}
signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T;cin>>T;
	while(T--) solve();
	return 0;
}

Problem - D - Codeforces

解題思路

  • 感覺難點在於讀題,題目的三條性質其實表示這是一顆層序遍歷的樹,除0點外每一個節點只有一個孩子
  • 我們可以透過一個佇列進行模擬詢問,只要找出節點1的孩子之後剩下的就依次詢問即可
  • 詳情見程式碼部分
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int fa[N];
int ask(int x,int y){
	cout<<"? "<<x<<" "<<y<<endl;
	int tmp;cin>>tmp;
	return tmp;
}
void solve(){
	int n;cin>>n;
	fa[1]=0;
	queue<int> q;
	q.push(1);
	int now=2;
	while(now<n){
		int tmp=ask(1,now);
		if(tmp==1){
			fa[now]=0;
			q.push(now);
			now++;
		}
		else if(tmp==0){
			fa[now]=1;
			q.pop();//1出隊
			q.push(now);
			now++;
			break;
		}
	}
	while(now<n){
		int t=q.front();
		q.pop();
		int tmp=ask(t,now);
		if(tmp==0){
			fa[now]=t;
			q.push(now);
			now++;
		}
	}
	cout<<"! ";
	for(int i=1;i<n;i++) cout<<fa[i]<<" ";
	cout<<endl;
}
int main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T;cin>>T;
	while(T--) solve();
	return 0;
}

相關文章