Codeforces Ronda # 631 div1C (o div2E) Drazil Favoritos solución a un problema Montón

enlaces a los temas: https://codeforces.com/contest/1329/problem/C

O: https://codeforces.com/contest/1330/problem/E

( He instalado b, y le dará un vistazo a mi tecnología de línea de prensa , niebla)

Codicioso, si la raíz puede borrar la eliminación, de lo contrario la izquierda y DFS derecha, respectivamente raíces como hijo sobre (explicar, si se elimina un nodo dentro del plomo profundidad a 0 g apareció para explicar no se pueden eliminar, ya que resultó en una lata final no sea tan alto g montón completo binario)

Aquí proporcionar alguna pseudo código y el código de aspecto brillante-reales

void dfs(int x){
	if(a[x]==0)return;
	while( 可以删除a[x] ) 删除a[x], 记录x; //记录x因为最后要输出这个
	dfs(x*2); dfs(x*2+1);
}

En cuanto a por qué esto es que la codicia, ¿cuál es la comprensión emocional, cada operación, si se elimina un nodo mayores rendimientos hijo deben eliminarlo tan bueno como un padre, por lo que en primer lugar hay que seguir para eliminar el nodo raíz. Si encuentra un nodo no puede ser eliminado, sino que también es el hijo mayor no debe ser borrada, para que pueda encontrar toda la cadena (compuesta por el gran gran hijo nieto) no se puede eliminar. Es hora de considerar un nodo en esta cadena de hijo pequeño, sólo se eliminará una vez que el cambio es pequeño, no puede ponerse de pie para convertirse en el hijo mayor, lo que garantiza la estabilidad de toda la cadena, por lo que no se puede eliminar el nodo después de todo, no se pueden borrar ( cómo parece un poco triste), y por lo tanto no tiene en cuenta el nodo no se pueden eliminar

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=2100010; typedef long long ll; ll read(){ll x; if(scanf("%lld",&x)==-1)exit(0); return x;}
//#define int ll
int a[N],h,g;
#define lc (x*2) //左儿子编号
#define rc (x*2+1) //右儿子编号
#define bigch (a[lc]>a[rc]?lc:rc) //左右儿子中较大的儿子编号
int height(int x){ //x的高度,即删除x会让多少个数变化
	if(a[x]==0)return 0;
	return height(bigch)+1;
}
void del(int x){ //删除x,和题目里代码的功能一模一样
	if(a[x]==0)return;
	a[x]=a[bigch];
	del(bigch);
}
vector<int> ans;
void dfs(int x,int dep){ //递归求解,这个函数就是上文伪代码抽象出来的
	if(a[x]==0)return;
	while(height(x)+dep>g)del(x),ans.push_back(x);
	dfs(lc,dep+1); dfs(rc,dep+1);
}
signed main(){
	int T=read();
	while(T--){
		h=read(),g=read();
		fill(a,a+(1<<h)*2+2,0); ans.clear();
		repeat(i,1,(1<<h))a[i]=read();
		dfs(1,0);
		ll s=0; repeat(i,1,(1<<g))s+=a[i];
		cout<<s<<endl;
		for(auto i:ans)cout<<i<<' '; cout<<endl;
	}
	return 0;
}

Supongo que te gusta

Origin www.cnblogs.com/axiomofchoice/p/12632461.html
Recomendado
Clasificación