F. Editorial para Dois (resposta de dois pontos + arrependimento e ganância)

F. Editorial para Dois (resposta de dois pontos + arrependimento e ganância)

F. Editorial para Dois

1. Problema

Dado um nnn ekkk e um comprimentonnmatriz n . agora dennEntre n números, escolhakkK números são chamados de subsequências. Em seguida, divida esta subsequência em duas partes, denotadas como subsequência 1 e subsequência 2. Então, tanto a subsequência 1 quanto a subsequência 2 têm uma soma correspondente. Essas duas somas podem ser comparadas a um valor máximo. Agora o que queremos éo valor mínimo do valor máximo.

2. Análise

Aqui está uma rotina muito comum: quando a questão nos pede para encontrar o valor mínimo do valor máximo ou o valor máximo do valor mínimo, geralmente usamos a dicotomia para resolvê-la.

Nós dividimos a resposta final aqui.

Por dois pontos, a dificuldade está em checar checarA escrita da função check .

Nesta questão, marque marqueA função da função de verificação é julgar meio meiono processo de dicotomiaÉ o valor médio razoável.

insira a descrição da imagem aqui
Então isso escolhe no máximo k 1 k1O processo dos números k 1 usaarrependimento eganância. A ideia de arrependimento e ganância é quando a soma dos números selecionados é menor quemeio meioQuando for meio , escolha o maior número possível de números, quando for maior quemeio meioQuando mid , o valor máximo dos números selecionados é excluído, o objetivo é deixar mais espaço para que mais números sejam selecionados, e esse processo de seleção do valor máximo pode ser otimizado com um grande heap raiz.

Além disso, a localização da divisão de prefixo e sufixo na figura é incerta, portanto, precisamos enumerar todas as localizações de divisão para encontrar uma solução viável.

Portanto, podemos primeiro pré-processar os números mais selecionados k 1 , k 2 k1,k2 entre todos os prefixos e sufixos usando arrependimento e ganância.k 1 ,k 2 . Em seguida, enumere as posições de divisão e julgue se existe um grupo dek 1 + k 2 ≥ k k1+k2 \geq kk 1+k2_ _k .

3. Código

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;


bool check(int maxv, int n, vector<int>a, int k)
{
    
    
	vector<int>f(n + 1, 0), g(n + 1, 0);
	priority_queue<int>q, qq;
	int sum = 0;
	for(int i = 0; i < n; i ++)
	{
    
    
		if(sum + a[i] <= maxv)
		{
    
    
			sum += a[i];
			q.push(a[i]);
			f[i + 1] = f[i] + 1;
		}
		else
		{
    
    
			q.push(a[i]);
			sum += a[i];
			sum -= q.top();
			q.pop();
			f[i + 1] = f[i];
		}
	}
	sum = 0;
	reverse(a.begin(), a.end());
	for(int i = 0; i < n; i ++)
	{
    
    
		if(sum + a[i] <= maxv)
		{
    
    
			sum += a[i];
			qq.push(a[i]);
			g[i + 1] = g[i] + 1;
		}
		else
		{
    
    
			sum += a[i];
			qq.push(a[i]);
			sum -= qq.top();
			qq.pop();
			g[i + 1] = g[i]; 
		}
	}

	for(int i = 1; i <= n; i ++ )
	{
    
    
		if(f[i] + g[n - i] >= k)
			return true;			
	}
	return false;

}

void solve()
{
    
    
	int n, k;
	cin >> n >> k;
	vector<int>a(n);
	int sum = 0;
	for(int i = 0; i < n; i ++)
	{
    
    
		cin >> a[i];
		sum += a[i];
	}
	int l = 0, r = sum;
	while(l < r)
	{
    
    
		int mid = l + r >> 1;
		if(check(mid, n, a, k))
			r = mid;
		else
			l = mid + 1;
	}
	cout << l << endl;
}

signed main()
{
    
    
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
}

Acho que você gosta

Origin blog.csdn.net/weixin_72060925/article/details/131021278
Recomendado
Clasificación