Codeforces Round # 693 (Div. 3) Relatório de solução de problemas

Link do assunto: https://codeforces.com/contest/1472

A. Cartões para amigos

Tópico

Um pedaço de papel tem w de comprimento e h de largura. Se w ou h for um número par, então ele pode ser dividido em duas metades de papel. Repita a mesma ação para os dois pedaços de papel e pergunte se um pedaço de o papel pode ser dividido em não menos que n

Ideias

Decomponha w e h separadamente e continue dividindo por 2 até que eles não possam ser divididos, e divida-os nas partes t1 e t2, de modo que haja t1 * t2 partes no total.

Aqui você pode dividir pela força ou usar operações de bit diretamente, ou seja, lowbit (pegue o número restante da posição do último 1 no binário).

Código AC

violência

#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;
}

lowbit

#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. Divisão Justa

Tópico

n pedaços de açúcar, o peso é 1 ou 2, pergunte se pode ser dividido em duas partes do mesmo peso

Ideias

Encontre o número de 1, t1, o número de 2, t2 e o peso total s.

Se s for um número ímpar, definitivamente não funcionará;

Se for dividido em duas metades, o peso atribuído a cada pessoa é um número ímpar, mas não há bala com peso 1, isso não funciona.

Código 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. Saltos longos

Tópico

Os n números são armazenados no array a, começando da i-ésima posição, a posição do meio tt é inicializada para i, e então a distância de a [tt] pode ser saltada a cada vez.

Se tt <= n, então você pode continuar a saltar, caso contrário o jogo termina, tmp é a soma dos pesos do salto intermediário, e agora pergunte qual é o valor máximo deste tmp.

Ideias

Cada posição pode pular o tempo todo, saindo de n. Se você atravessar da esquerda para a direita, por exemplo, se 1 pode pular para 6 e 3 pode pular para 6, então 6 aqui saltou duas vezes, muitas operações repetidas, mas podemos atravessar de trás para a frente, então pode ser equivalente a memoização, um salto é o suficiente.

Código 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. Jogo par-ímpar

Tópico

Duas pessoas se revezam para pegar n pedras até terminarem. Alice fica em primeiro lugar, Bob em segundo.

Se o peso wi da pedra tirada por Alice for um número par, então sua pontuação será somada wi, caso contrário, não será somada;

Se o peso wi da pedra tirada por Bob for ímpar, sua pontuação será somada wi, caso contrário, não será somada.

Pergunte quem ganha ou empata no final.

Ideias

Se eu quiser escolher, devo escolher o mais pesado de cada vez. A melhor maneira de somar pontos. Se não posso somar pontos, então você deve ter adicionado pontos. Não, não posso adicioná-los a você, pegue-o .

Código 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. Colocação correta

Tópico

N crianças fazem fila para tirar fotos, e cada criança tem atributos de comprimento e largura wi, hi. Se i deve ser classificado antes de j, deve satisfazer wi <wj && hi <hj ou wi <hj && hi <wj.

Agora pergunte para cada filho i, imprima um subscrito (arbitrário) do filho que pode ser arranjado na frente dele, se não existir, imprima -1

Ideias

Em primeiro lugar, se for estipulado que wi é o menor valor entre (wi, hi) e hi é o maior valor entre (wi, hi), então só precisa ver se a condição wi <wj && hi <hj é satisfeita

Em seguida, você pode classificar por wi primeiro e depois por hi para garantir que w à esquerda seja menor ou igual aw à direita;

A ideia de ponteiros duplos, i, j. i atravessa a matriz, j persegue, se a [j] .w <a [i] .w então tmp atualiza o valor mínimo de a [j] .h, id é a posição do valor mínimo atualizado, se tmp <a No caso de [i] .h, a criança na posição id pode ficar na frente da criança a [i] .id neste momento.

Código 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;
}

 

Acho que você gosta

Origin blog.csdn.net/weixin_43911947/article/details/112217993
Recomendado
Clasificación