Codeforces Round # 693 (Div. 3) 문제 해결 보고서

제목 링크 : https://codeforces.com/contest/1472

A. 친구 용 카드

이야기

한 장의 종이는 길이가 w이고 폭이 h입니다. w 또는 h가 짝수이면 두 개의 종이로 나눌 수 있습니다. 두 장의 종이에 대해 동일한 동작을 반복하고 한 장의 종이는 n 이상으로 나눌 수 있습니다

아이디어

w와 h를 따로 분해하고 나눌 수 없을 때까지 2로 계속 나누고 t1과 t2 부분으로 나눠서 총 t1 * t2 부분이 있습니다.

여기서 강제로 나누거나 비트 연산을 직접 사용할 수 있습니다. 즉, lowbit (바이너리의 마지막 1 위치에서 남은 숫자를 가져옴)입니다.

AC 코드

폭력

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
	int t; cin >> t;
	while(t --){
		int w, h, n;
		cin >> w >> h >> n;
		int t1 = 1, t2 = 1;
		while(w % 2 == 0) {
			t1 *= 2;
			w /= 2;
		}
		while(h % 2 == 0){
			t2 *= 2;
			h /= 2;
		}
		if(t1 * t2 >= n) puts("YES");
		else puts("NO");
	}
	return 0;
}

로우 비트

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) x & (-x)
int main(){
	int t; cin >> t;
	while(t --){
		int w, h, n;
		cin >> w >> h >> n;
		int t1 = lowbit(w), t2 = lowbit(h);
		if(t1 * t2 >= n) puts("YES");
		else puts("NO");
	}
	return 0;
}

B. 공정한 부문

이야기

설탕 n 조각, 무게는 1 또는 2입니다. 같은 무게의 두 부분으로 나눌 수 있는지 묻습니다.

아이디어

1의 수, t1, 2의 수, t2, 총 중량 s를 구합니다.

s가 홀수이면 확실히 작동하지 않습니다.

두 개로 나눈 경우 각 사람에게 할당 된 가중치는 홀수이지만 가중치가 1 인 사탕이 없으면 작동하지 않습니다.

AC 코드

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
	int t; cin >> t;
	while(t --){
		int s = 0, n, t1 = 0, t2 = 0, x;
		cin >> n;
		while(n --){
			cin >> x;
			t1 += (x == 1);
			t2 += (x == 2);
			s += x;
		}
		if(s % 2){
			puts("NO");
			continue;
		}
		s /= 2;
		if(s % 2 && !t1) puts("No");
		else puts("YES"); 
	}
	return 0;
}

C. 멀리뛰기

이야기

n 개의 숫자는 i 번째 위치부터 시작하여 배열 a에 저장되고 중간 위치 tt는 i로 초기화 된 다음 a [tt]의 거리를 매번 점프 할 수 있습니다.

tt <= n이면 계속 점프 할 수 있습니다. 그렇지 않으면 게임이 종료되고 tmp는 중간 점프의 가중치의 합입니다. 이제이 tmp의 최대 값이 얼마인지 묻습니다.

아이디어

각 위치는 항상 점프하여 n에서 뛰어 내릴 수 있습니다. 예를 들어 왼쪽에서 오른쪽으로 횡단하면 1이 6으로 점프하고 3이 6으로 점프 할 수 있다면 여기서 6은 두 번 점프했습니다. 그러나 우리는 뒤에서 앞으로 이동할 수 있으므로 메모 화와 동일 할 수 있습니다. 한 번의 점프로 충분합니다.

AC 코드

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 10;
ll a[maxn], dp[maxn]; // dp[i]就是从i位置开始跳出n需要加的权值
int main(){
	int t; cin >> t;
	while(t --){
		int n; scanf("%d",&n);
		for(int i = 1; i <= n; i ++){
			scanf("%lld", &a[i]);
		}
		for(int i = 1; i <= n; i ++) dp[i] = 0;
		ll ans = 0;
		for(int i = n; i >= 1; i --){
			ll d = i + a[i];
			dp[i] += a[i] + (d <= n ? dp[d] : 0);
			ans = max(ans, dp[i]);
		}
		cout << ans << endl;
	}
	return 0;
}

D. 짝수 홀수 게임

이야기

두 사람이 차례대로 끝날 때까지 n 개의 돌을 가져갑니다. 앨리스가 먼저, 밥이 2 위를 차지합니다.

Alice가 가져온 돌의 무게 wi가 짝수이면 그녀의 점수가 추가되고 그렇지 않으면 추가되지 않습니다.

Bob이 가져간 돌의 무게 wi가 홀수이면 그의 점수가 추가됩니다. 그렇지 않으면 추가되지 않습니다.

누가이기거나 무승부를하는지 물어보십시오.

아이디어

선택하려면 매번 가장 무거운 것을 선택해야합니다. 포인트를 추가하는 가장 좋은 방법입니다. 포인트를 추가 할 수 없다면 포인트를 추가 했어야합니다. 아니요, 추가 할 수 없습니다. .

AC 코드

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 2e5 + 10;
ll a[maxn];
int main(){
	int t; cin >> t;
	while(t --){
		int n, x; cin >> n;
		ll t1 = 0, t2 = 0;
		for(int i = 1; i <= n; i ++) {
			cin >> a[i];
		}
		sort(a + 1, a + n + 1, greater<int>()); //从大到小排序
		for(int i = 1; i <= n; i ++){
			if(i % 2 == 1 && a[i] % 2 == 0) t1 += a[i]; //Alice先手 偶数加分
			if(i % 2 == 0 && a[i] % 2 == 1) t2 += a[i]; //Bob后手 奇数加分
		}
		if(t1 > t2) puts("Alice");
		else if(t1 < t2) puts("Bob");
		else puts("Tie");
	}
	return 0;
}

E. 올바른 배치

이야기

N 명의 아이들이 줄을 서서 사진을 찍고, 각 아이들은 길이와 너비 속성 wi, hi를 가지고 있습니다. i가 j보다 먼저 순위가 매겨 질 경우 wi <wj && hi <hj 또는 wi <hj && hi <wj를 충족해야합니다.

이제 각 자식 i를 요청하고 자식 앞에 배치 할 수있는 자식의 첨자 (임의)를 출력합니다 (존재하지 않는 경우 출력 -1).

아이디어

우선, (wi, hi) 중 wi가 작은 값이고 (wi, hi) 중 hi가 큰 값이라고 규정 된 경우 wi <wj && hi <hj 조건을 만족하는지 확인하기 만하면됩니다.

그런 다음 먼저 wi로 정렬 한 다음 hi로 정렬하여 왼쪽의 w가 오른쪽의 w보다 작거나 같은지 확인할 수 있습니다.

이중 포인터의 아이디어, i, j. i는 배열을 순회하고, j는 a [j] .w <a [i] .w를 추적하고, tmp는 a [j] .h의 최소값을 업데이트하고, id는 업데이트 된 최소값의 위치입니다 (tmp <a). [i] .h의 경우, 이때 id 위치에있는 아이가 아이 a [i] .id 앞에 설 수 있습니다.

AC 코드

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(x) x & (-x)
#define pp pair<int, int>
const int maxn = 2e5 + 10;
struct node{
	int x, y, id;
	bool operator < (const node &a) const{
		if(x != a.x) return x < a.x;
		return y < a.y;	
	}
}a[maxn];
int dp[maxn];
int main(){
	int t, n;
	cin >> t;
	while(t --){
		cin >> n;
		for(int i = 1; i <= n; i ++){
			cin >> a[i].x >> a[i].y;
			if(a[i].x > a[i].y) swap(a[i].x, a[i].y);
			a[i].id = i; dp[i] = -1;
		}
		sort(a + 1, a + n + 1);
		int tmp = 0x3f3f3f3f, id = -1, j = 1;
		for(int i = 1; i <= n; i ++){
			while(j < i && a[j].x < a[i].x){
				if(tmp > a[j].y){
					tmp = a[j].y;
					id = a[j].id;
				} j ++;
			}
			if(tmp < a[i].y) dp[a[i].id] = id;
		}
		for(int i = 1; i <= n; i ++){
			if(i > 1) cout << " ";
			cout << dp[i];
		}
		cout << endl;
	}
	return 0;
}

 

추천

출처blog.csdn.net/weixin_43911947/article/details/112217993