首页 > 其他分享 >P4785 [BalticOI 2016 Day2] 交换 题解

P4785 [BalticOI 2016 Day2] 交换 题解

时间:2024-06-05 21:16:09浏览次数:9  
标签:mn val rs int 题解 P4785 Day2 ls id

看到 \(i\) 和 \(\lfloor \frac{i}{2} \rfloor\),考虑一颗二叉树。题目的操作相当于按顺序交换当前节点和左右儿子的权值。

假设当前考虑的节点为 \(id\),左儿子为 \(ls\),右儿子为 \(rs\),当前这些点的值分别为 \(A,B,C\)。

因为 \(id\) 的位置最靠前,最终又要字典序最小,所以要尽可能让 \(a_{id}\) 最小。

分三种情况讨论:

  • \(\min(A,B,C)=A\)

肯定都不交换,因为要贪心地使 \(a_{id}\) 最小,如果交换了任意一个的话 \(a_{id}\) 就肯定大于 \(A\) 了。

  • \(\min(A,B,C)=B\)

因为要让 \(a_{id}\) 最小,所以肯定会交换 \((id,ls)\),并且不会交换 \((id,rs)\)。

  • \(\min(A,B,C)=C\)

会发现肯定要交换 \((id,rs)\),但是不确定要不要交换 \((id,ls)\),也就是不确定 \(A\) 放左边还是 \(B\) 放左边。直接贪心肯定不行,我们假设 \(mn = \min(A,B)\)。定义函数 \(f(id,val)\) 表示将当前节点为 \(id\),值为 \(val\),最终 \(val\) 的位置在哪。看 \(mn\) 放哪边的最终位置(即 \(f(ls,mn)\) 和 \(f(rs,mn)\))更小即可。为啥?因为若 \(mn\) 不放最终位置更小的那边,那么这个位置的值肯定会更大,而放这个位置的话影响的位置更靠后,所以放小的这边更优。

那如何求 \(f(id,val)\) 呢,会发现对于同一个 \(id\),可能的 \(val\) 只有 \(\log\) 个(\(id\) 的祖先以及祖先的兄弟节点),那直接暴力转移再记忆化一下即可。

时间复杂度的瓶颈在求 \(f\),复杂度 \(O(n \log^2 n)\)。

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 4e5 + 10;
int n,a[MAXN],ans[MAXN];
#define ls id << 1
#define rs id << 1 | 1
map <int,int> mp[MAXN];
inline int dfs(int id,int val) {
	if(mp[id].count(val)) return mp[id][val];
	int res = id,A = val,B = a[ls],C = a[rs];
	if(B == 0 && C == 0) res = id;
	else if(C == 0) {
		if(B < A) res = ls;
		else res = id;
	} else {
		if(A < B && A < C) res = id;
		else if(B < A && B < C) res = dfs(ls,val);
		else {
			int mx = max(A,B),mn = min(A,B);
			int LS = dfs(ls,mn),RS = dfs(rs,mn);
			if(A < B) res = min(LS,RS);
			else {
				if(LS < RS) res = dfs(rs,val);
				else res = dfs(ls,val);
			}
		}
	} return mp[id][val] = res;
}
inline void solve(int id) {
	int A = a[id],B = a[ls],C = a[rs];
	if(B == 0 && C == 0) return;
	else if(C == 0) {
		if(B < A) swap(a[id],a[ls]);
		return;   
	} else {
		if(A < B && A < C) solve(ls),solve(rs);
		else if(B < A && B < C) {
			swap(a[id],a[ls]);
			solve(ls),solve(rs); 
		} else {
			a[id] = C;
			int mx = max(A,B),mn = min(A,B);
			int LS = dfs(ls,mn),RS = dfs(rs,mn);
			if(LS < RS) a[ls] = mn,a[rs] = mx;
			else a[rs] = mn,a[ls] = mx;
			solve(ls),solve(rs);
		}
	} return;
}
signed main() {
	cin >> n;
	for(int i = 1;i <= n;i++) cin >> a[i];
	solve(1);
	for(int i = 1;i <= n;i++) cout << a[i] << " ";	
	return 0; 
} 

标签:mn,val,rs,int,题解,P4785,Day2,ls,id
From: https://www.cnblogs.com/Creeperl/p/18233783

相关文章

  • 题解:SP1442 CHAIN - Strange Food Chain
    双倍经验:P2024[NOI2001]食物链思路:一眼鉴定为并查集。观察题目发现有三种状态,考虑使用种类并查集(又称扩展域并查集)。既然有三种状态那么种类并查集自然也要开三倍。CODE:#include<bits/stdc++.h>usingnamespacestd;intfa[150010];intGet_Find(intx){//寻找父节点......
  • P1654 OSU! 题解
    P1654OSU!题解题目链接好题!但不得不说早期洛谷的题解质量是真的差,感觉没有一篇题解是讲的特别清楚的,我看了好久才搞懂。下面是我认为的一种更规范的解题过程。首先,我们设随机变量\(X_i\)表示从\(i\)向左的极长1串的长度,并且对于任意的\(i\),我们要想办法求出\(E(X_i......
  • (第26天)【leetcode题解】226、翻转二叉树 589、N叉树的前序遍历 590、N叉树的后序遍
    目录226、翻转二叉树题目描述思路代码589、N叉树的前序遍历题目描述思路代码590、N叉树的后序遍历题目描述思路代码思考总结226、翻转二叉树题目描述给你一棵二叉树的根节点root,翻转这棵二叉树,并返回其根节点。示例:输入:root=[4,2,7,1,3,6,9]输出:[4,7,2,9,......
  • python基础学习day2
    python基础1、注释#单行注释'''三单引号注释'''"""三双引号多行注释"""2、数据类型一、整型(int)表示人的年龄、号码等age=18#age=int(18)print(id(age))print(type(age))print(age)二、浮点型(float)表示身高、体重、薪资salary=2.1#sala......
  • Codeforces Round 949题解(A、B、C)
    A.TurtleandPiggyArePlayingaGame首先\(p\)选\(2\)的话除得最慢,得的分多。考虑二进制表示,如果\(x=(1000000000)_{bin}\),则每次除以\(2\)都是相当于右移一位,除完之后仍然是\(2\)的倍数,变成\(1\)的步数就是把最高位的\(1\)移动到\(0\)位的步数。因为\(2l\ler\),所以\(l......
  • P8125 [BalticOI 2021 Day2] The short shank 题解
    首先会发现若\(t_i<=T\)的话那么他最终一定会造反。我们只考虑\(t_i>T\)的情况。设\(lst_i\)表示\(i\)左边第一个可以影响(使他造反)到\(i\)的位置,那么我们一定要在\([lst_i,i]\)这个区间中的某一个位置放上床垫才能使\(i\)不造反。这样有一个\(O(nd)\)的dp,但......
  • 2024年03月 GESP等级认证Python编程(一级)试题解析
    【单选题】(每题2分)1、小杨的父母最近刚刚给他买了一块华为手表,他说手表上跑的是鸿蒙,这个鸿蒙是?()A、小程序   B、计时器   C、操作系统   D、神话人物   正确答案:C2、中国计算机学会(CCF)在2024年1月27日的颁奖典礼上颁布了王选奖,王选先生的重大贡献是?()A、制......
  • Codeforces Round 950 (Div. 3)个人题解(A~F1)
    CodeforcesRound950(Div.3)个人题解(A~F1)题解火车头#define_CRT_SECURE_NO_WARNINGS1#include<iostream>#include<vector>#include<algorithm>#include<set>#include<unordered_map>#include<cstring>#include<cstdio&......
  • 按按钮题解
    按按钮题解在量体温,打不了代码,来写题解。赞美lwq,三句话让我跟上了课堂节奏。题意数轴\(n\)个按钮,第\(i\)个按钮在坐标\(i\)。有\(m\)次询问,\(i\)询问为在时刻\(t_i\)按下\(b_i\)。可以在时刻\(0\)安排一些机器人,机器人可以花\(1\)单位时间向左或右移动\(1\)......
  • acwing329 围栏障碍训练场 题解
    考试压轴题,意识到这题是线段树优化\(dp\)时追悔莫及。为了简化题目,我将从起点到原点变成了从原点到起点(这样就可以省去两个数组的空间)。想到设\(dp_{i,j}\)表示在第\(i\)层,奶牛们在\(j\)列时的最小移动范围,则转移方程为(设输入为\(l,r\)):\[\begin{cases}dp_{i,j}=dp_{......