Codeforces Round #826 (Div. 3)D. Masha and a Beautiful Tree

Codeforces Round #826 (Div. 3)

 

 

 

题意: 给你给你一个高度为n的完全二叉树(包含的子节点为2^n),然后给你n个数分别对应子树

的n个结点,每次可以进行一个操作:交换树的任何非叶顶点,并交换它的左右子结点(以及它们的

子树)。        问最后组成的序列能不能形成一个递增的序列,如果能就输出最少的操作数,不能

就输出-1。

思路:因为最后要组成递增的序列,所以如果我的子树不是单调递增的话,那么我的整个区间就

不是递增的,所以我们要从子树往上不断更新成单调递增的序列。

然后我们每次修改都是从子区间往上更新。

如果子区间不是递增的那么整个序列也不可能是递增的,那么我们要从子树开始不断向上交换,

如果区间长度为l,r那么左区间的最大的下标是mid,所以更新的值也只能是swap(i,i+(r-l+1>>1)); ,r-l+1是一个半区的长度

对子区间进行考虑:如果当前节点的两个子区间不是递增的话(s[l] > s[r] ),即左子树的第一个节点大于右子树的第一个节点,就要进行交换,不断dfs交换排序(归并排序好像是有点像),如果排序后的子序列是递增的就输出需要的次数,否则输出-1。

#include<cstdio>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include<vector>
#include<queue>
#include<map>
#define ll long long 
using namespace std;

const int N=1000000+100;
int n ,m,h;
ll s[N];
int cnt;

void dfs(int l,int r )//要修改的左右区间,首先肯定是从子区间不断
{
	if(l==r)return ;
	int mid=l+r>>1;//左半区间的的端点
	int len=r-l+1>>1;//要更新的长度
	dfs(l,mid),dfs(mid+1,r);//继续递归子区间image.png
	if(s[l]>s[r])//如果修改后的字区间不满足递增
	{
		cnt++;
		for(int i =l;i<=mid;i++)//对左半边的区间进行排序
		swap(s[i],s[i+len]);
	}
}

/*
因为最后要组成递增的序列,然后我们每次修改都是从子区间往上更新。
如果子区间不是递增的那么整个序列也不可能是递增的,那么我们要从子树开始不断向上交换,
如果区间长度为l,r那么左区间的最大的下标是mid,所以更新的值也只能是swap(i,i+(r-l+1>>1)); ,r-l+1是一个半区的长度

*/

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		cnt=0;
		cin>>n;
		for(int i =1;i<=n;i++)cin>>s[i];
		dfs(1,n);
		int flag=0;
		for(int i =1;i<=n;i++)
		{
			if(s[i]>s[i+1]&&i+1<=n)
			flag=1;
		}
		if(flag)cout<<"-1\n";
		else cout<<cnt<<endl;
	}
	

	return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值