• codeforces#1329C


    C - Drazil Likes Heap

    题意:

    给定一个高度为$h$的完全二叉树,也满足最大堆的性质,执行下面操作,得到一个高度为$g$的完全二叉树

    求操作后的完全二叉树的最小权值和,和操作的$id$

    分析:

    看了题解写的

    从下往上考虑,定义h树为还没操作的树,定义g树为操作结束的树,经过观察发现,g树的叶子一定是当前位置在h树的最小节点,g树的其它节点只需要满足两个条件,第一,比它在g树的两个儿子要大,第二,来自于h树中当前位置的子树,所以贪心策略是一直找满足条件的最小值

    构造方法:找到那些需要删除的节点,然后根据编号从大到小删除它们,因为大编号的删除不影响小编号的位置

    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,a,b) for (int i=(a);i<=(b);i++)
    #define per(i,a,b) for (int i=(b);i>=(a);i--)
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define SZ(x) ((int)(x).size())
    
    typedef long long ll;
    typedef vector<int> VI;
    typedef pair<int,int> PII;
    
    ll mod=998244353 ;
    const int maxn=(1<<20)+7;
    vector<PII>ve[maxn];
    ll sum;
    int ans[maxn],a[maxn],book[maxn],g,h;
    void dfs(int x){
    	if(x*2>(1<<h)-1){
    		ve[x].pb(mp(a[x],x));
    		return ;
    	}
    	dfs(x*2);
    	dfs(x*2+1);
    	int st=0,en=0;
    	while(st<SZ(ve[x*2])&&en<SZ(ve[x*2+1])){
    		if(ve[x*2][st]<ve[x*2+1][en])ve[x].pb(ve[x*2][st]),st++;
    		else ve[x].pb(ve[x*2+1][en]),en++;
    	}
    	while(st<SZ(ve[x*2]))ve[x].pb(ve[x*2][st]),st++;
    	while(en<SZ(ve[x*2+1]))ve[x].pb(ve[x*2+1][en]),en++;
    	ve[x*2].clear();
    	ve[x*2+1].clear();
    	ve[x].pb(mp(a[x],x));
    	if(x<=(1<<g)-1){
    		int v=max(ans[x*2],ans[x*2+1]);
    		//upper_bound(ve[x].begin(),ve[x].end(),mp(v,1e9));
    		PII zz=*upper_bound(ve[x].begin(),ve[x].end(),mp(v,(int)1e9));
    		ans[x]=zz.fi;
    		book[zz.se]=1;
    		sum+=ans[x];
    	}
    }
    int main(){
    	int T;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d %d",&h,&g);
    		rep(i,1,(1<<h)-1)scanf("%d",&a[i]);
    		dfs(1);
    
    		printf("%lld
    ",sum);
    		int fla=0;
    		per(i,1,(1<<h)-1){
    			if(book[i]==0){
    				if(fla==0)printf("%d",i),fla=1;
    				else printf(" %d",i);
    			}else book[i]=0;
    		}
    		printf("
    ");
    		rep(i,1,(1<<h)-1)ans[i]=0;
    		ve[1].clear();
    		sum=0;
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    异常作业
    多态作业
    封装和继承作业
    类和对象作业
    多重循环、方法作业
    选择语句+循环语句作业
    数据类型和运算符作业
    初识Java作业
    C 数据结构堆
    C基础 旋转数组查找题目
  • 原文地址:https://www.cnblogs.com/carcar/p/12641971.html
Copyright © 2020-2023  润新知