首页 > 其他分享 >P9507 [BalkanOI2018] Popa 题解

P9507 [BalkanOI2018] Popa 题解

时间:2023-08-09 13:55:25浏览次数:47  
标签:rt Popa right return int 题解 BalkanOI2018 todo left

原题传送门

题目描述

Ghiță 有一个下标从 \(0\) 开始的正整数序列 \(S\)。因为他是喀尔巴阡的国王,所以他想要构造一个节点编号为 \(0,1,\ldots ,N-1\) 的二叉树,满足:

  • 树的中序遍历按节点编号升序排列。二叉树的中序遍历由以根的左子节点(如果存在)为根形成的子树的中序遍历,根的节点编号和以根的右子节点(如果存在)为根形成的子树的中序遍历顺次连接组成。
  • 如果 \(x\) 是 \(y\) 节点的父亲,那么 \(S_x\) 整除 \(S_y\)。

二叉树是一种树形结构,每个节点最多有两个子节点,分别称为左子节点和右子节点。

不幸的是,著名的亡命之徒 Andrii Popa 偷走了序列 \(S\),Ghiță 不能直接获取到。但对于任意两个连续的子序列 \([a,b]\) 和 \([c,d]\),他可以使用最先进的技术(他的手机)求出 \(\gcd[a,b]\) 是否等于 \(\gcd [c,d]\),其中 \(\gcd[x,y]\) 指 \(S_x,S_{x+1},S_{x+2},\ldots ,S_y\) 的最大公因数。不幸的是,这项技术十分昂贵——如果 Ghiță 使用超过 \(Q\) 次,他将会支付一大笔罚金。请帮他在使用这项技术最多 \(Q\) 次的情况下构建出他想要的树。保证这是可能的。任何合法的构建方案都可以被接受。

数据范围

子任务编号 限制 分值
\(1\) \(N=100,Q=10^4\) \(37\)
\(2\) \(N=10^3,Q=2\times 10^4\) \(24\)
\(3\) \(N=10^3,Q=2\times 10^3\) \(39\)

思路

分析条件。

树的中序遍历按编号升序排列。

想到 BST。

如果 \(x\) 是 \(y\) 节点的父亲,那么 \(S_x\) 整除 \(S_y\)。

发现整除具有传递性,想到笛卡尔树。

\(O(n \log n)\) 做法

注意到树根一定是所有树的 \(\gcd\),可以二分树根所在的区间,\(\Theta(\log s)\) 次询问,其中 \(s\) 为区间长度。

找到树根后,两边递归建树。

namespace O_n_log_n{ // }{{{
int findroot(int l, int r){
	while(r-l > 1){
		int mid = (l+r)/2;
		if(query(l, mid-1, l, r-1)){
			r = mid;
		} else {
			l = mid;
		}
	}
	return l;
}
int build(int l, int r, int *left, int *right){
	if(l == r) return -1;
	int rt = findroot(l, r);
	left[rt] = build(l, rt, left, right);
	right[rt] = build(rt+1, r, left, right);
	return rt;
}
int solve(int in, int *left, int *right){
	return build(0, in, left, right);
}
} // {}}}

\(\Theta(n)\) 做法

回忆笛卡尔树的 \(\Theta(n)\) 建树:维护目前全树的右链。

考虑右链末端点 \(u\),及将要加入树中的点 \(v\)。发现 \(\gcd(u,v)=v\),则 \(v\) 为 \(u\) 的祖先一定满足题意,类似笛卡尔树,将 \(u\) 出栈即可。

对于 \(u\) 出栈后的点 \(u'\),发现 \(u'\) 和 \(v\) 不相邻,但 \(u'\) 到 \(v\) 均为 \(u'\) 的后代,它们的 \(\gcd\) 为 \(u'\),因此询问 \(u'\) 到 \(v\) 的 \(\gcd\) 等价于询问 \(\gcd(u',v)\)。

namespace O_n{ // }{{{
std::stack<int> todo;
int solve(int in, int *left, int *right){
	UP(i, 0, in){
		left[i] = right[i] = -1;
		if(todo.empty()){
			todo.push(i);
		} else {
			while(!todo.empty()){
				if(query(i, i, todo.top(), i)) {
					left[i] = todo.top();
					todo.pop();
				} else break;
			}
			if(!todo.empty()){
				right[todo.top()] = i;
			}
			todo.push(i);
		}
	}
	int rt;
	while(!todo.empty()){
		rt = todo.top();
		todo.pop();
	}
	return rt;
}
} // {}}}

完整代码:

#include <stack>
#define UP(i,s,e) for(auto i=s; i<e; ++i)
int query(int a, int b, int c, int d);
namespace solution{ // }{{{
constexpr int N = 1e3;
namespace O_n_log_n{ // }{{{
int findroot(int l, int r){
	while(r-l > 1){
		int mid = (l+r)/2;
		if(query(l, mid-1, l, r-1)){
			r = mid;
		} else {
			l = mid;
		}
	}
	return l;
}
int build(int l, int r, int *left, int *right){
	if(l == r) return -1;
	int rt = findroot(l, r);
	left[rt] = build(l, rt, left, right);
	right[rt] = build(rt+1, r, left, right);
	return rt;
}
int solve(int in, int *left, int *right){
	return build(0, in, left, right);
}
} // {}}}
namespace O_n{ // }{{{
std::stack<int> todo;
int solve(int in, int *left, int *right){
	UP(i, 0, in){
		left[i] = right[i] = -1;
		if(todo.empty()){
			todo.push(i);
		} else {
			while(!todo.empty()){
				if(query(i, i, todo.top(), i)) {
					left[i] = todo.top();
					todo.pop();
				} else break;
			}
			if(!todo.empty()){
				right[todo.top()] = i;
			}
			todo.push(i);
		}
	}
	int rt;
	while(!todo.empty()){
		rt = todo.top();
		todo.pop();
	}
	return rt;
}
} // {}}}
} // {}}}
int solve(int in, int *left, int *right){
	return solution::O_n::solve(in, left, right);
}

标签:rt,Popa,right,return,int,题解,BalkanOI2018,todo,left
From: https://www.cnblogs.com/x383494/p/17616686.html

相关文章

  • 桐柏邀请赛 S15 题解
    定位:给中低段位一点压力,给中高段位一点信心!A发现只是单向变换\((0\to1)\),用两个变量维护位置最小值和最大值即可。#defineintlonglongintn,q,maxn,minn=1e18+1,x;signedmain(){ n=read(),q=read(); while(q--){ x=read(); maxn=max(maxn,x); minn=min(minn,x......
  • CF1857B Maximum Rounding 题解
    题面题目大意给定\(T\)组数据,每组数据一个自然数\(n\),可以多次选择第\(k\)位数进行四舍五入,求出四舍五入后该数的最大值。分析思路思想:贪心。这里给定了两种操作。四舍和五入。显然我们想要让最终的结果最大,我们的操作只能进行五入而不可以进行四舍。因为如果我们进行了......
  • 国标GB28181视频平台LntonGBS(源码版)国标平台级联时,通道上传上级宇视平台无法接收的问
    LntonGBS是基于公安部推出的GB/T28181协议开发的视频平台,在安防监控领域应用广泛。下面是一些关于LntonGBS平台的主要特点:GB/T28181协议兼容性、视频直播和转码、云端录像和存储、语音对讲和警告功能、平台级联功能。通过以上的功能和特点,LntonGBS平台能够满足安防监控领域各类场景......
  • sudo: a terminal is required to read the password; either use..... 问题解决方法
    转载自:sudo:aterminalisrequiredtoreadthepassword;eitheruse……问题解决方法_akaiziyou的博客-CSDN博客问题sudo:aterminalisrequiredtoreadthepassword;eitherusethe-Soptiontoreadfromstandardinorconfigureanaskpasshelper出现场景某个......
  • Codeforces Round 891 (Div. 3) 题解
    A.ArrayColoring因为:偶数+偶数=偶数奇数+奇数=偶数奇数+偶数=奇数所以设\(s1\)为奇数之和,\(s2\)为偶数之和\(s2\)必定是偶数如果奇数的个数为偶数,则\(s1\)为偶数;否则是奇数而在\(s1\)为奇数时,即使拿一个奇数加到\(s2\)里,那么也是不合法的所以直接判断奇数的......
  • CF1477E题解
    洛谷博客链接此篇未投洛谷题解,因为写得太菜了qwq。CF1477E&大户爱的送分题题解(CF1477E为我出的校内模拟赛的一道题——《大户爱的送分题》的待修版本)大户爱的送分题文件名OhtoAiFirst.cpp/.in/.out,时间限制\(1\)秒,空间限制\(256MB\)。注意第一个字母是O而不是0。题目背......
  • CF1030F题解
    CF1030F题解传送门 更好的阅读体验简化题意:有$n$个小球,每个小球在位置$a_i$,移动一格的代价是$w_i$,有两种操作,一种是将$w_x$改成$y$,一种是查询$\min\limits_{x=1}^n\{\sum\limits_{i=l}^rw_i\times(|a_x-a_i|+|x-i|)\}$。思路很好的线段树二分练手题。对于每......
  • CF1239E 题解
    CF1239E给定\(2n\)个数,将其重排成\(2\timesn\)的矩阵,最小化:从\((1,1)\)走到\((2,n)\),只可向右下走的所有方案中,途径所有数的和的最大值。\(n\le25,|V|\le5\times10^4\)。考场上有个\(n\le10\)的包,分值高达\(40\)。注意到\(\binom{20}{10}\approx10^5\)可枚......
  • 2023年 8月7日普及组南外集训题解
    A国家集训队题解注意数据已经是有序的,我还搞了个排序,我是智障所以只需要将第5个人到第16个人的成绩都预设成300,再把前4个人的成绩都预设成0,再看有没有人能超过第4个人就行了ac代码#include<iostream>usingnamespacestd;constintN=20;inta[N],ans=4;intmain(......
  • 2023年百度之星程序设计竞赛初赛1题解
    每次出题都出其不意---->群友蓝桥国三ac一道题根据官方的视频题解整理依据难度的划分第五题:促销糖果 分析:从答案出发想吃K个糖果,必定有k个糖纸,考虑换购,则有一张糖纸是不可以换的(因为你必须至少要买一颗糖果)则换购的数量为(k-1)/减去换购的糖果则是买的糖果packageLi2209;i......