【oi模拟赛】长乐中学-不知道多少年
改造二叉树
【题目描述】
小Y在学树论时看到了有关二叉树的介绍:在计算机科学中,二叉树是每个结点最多有两个子结点的有序树。通常子结点被称作“左孩子”和“右孩子” 。二叉树被用作二叉搜索树和二叉堆。随后他又和他人讨论起了二叉搜索树。
什么是二叉搜索树呢?二叉搜索树首先是一棵二叉树。设key[p]表示结点p上的数值。对于其中的每个结点p,若其存在左孩子lch,则key[p]>key[lch];若其存在右孩子rch, 则key[p]<key[rch];注意,本题中的二叉搜索树应满足对于所有结点,其左子树中的key小于当前结点的key,其右子树中的key大于当前结点的key。
小Y与他人讨论的内容则是,现在给定一棵二叉树,可以任意修改结点的数值。修改一个结点的数值算作一次修改,且这个结点不能再被修改。若要将其变成一棵二叉搜索树, 且任意时刻结点的数值必须是整数(可以是负整数或0) ,所要的最少修改次数。
相信这一定难不倒你!请帮助小Y解决这个问题吧。
【输入格式】
第一行一个正整数 n表示二叉树结点数。结点从 1~n 进行编号。
第二行 n 个正整数用空格分隔开,第 i 个数 ai 表示结点 i 的原始数值。
此后 n - 1 行每行两个非负整数 fa, ch,第 i + 2行描述结点 i + 1 的父亲编号 fa,以及父
子关系 ch,(ch = 0 表示 i + 1 为左儿子,ch = 1表示 i + 1为右儿子)。
结点 1一定是二叉树的根。
【输出格式】
仅一行包含一个整数,表示最少的修改次数。
【样例输入】
3
2 2 2
1 0
1 1
【样例输出】
2
【数据范围】
20 % :n <= 10 , ai <= 100.
40 % :n <= 100 , ai <= 200
60 % :n <= 2000 .
100 % :n <= 10 ^ 5 , ai < 2 ^ 31.
分析
中序遍历 + 最长不下降序列
错误代码如下
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100000+9;
#define lowbit(x) (x&-x)
int n;
int a[N], b[N], tot, c[N];
int lch[N], rch[N];
int mn = 2147483647, mx = -1;
void dfs(int x) {
if(!x) return ;
dfs(lch[x]);
b[++tot] = x;
dfs(rch[x]);
}
int ft[N], ans;
void add(int x, int k) {while(x <= mx) {ft[x] = max(ft[x], k); x += lowbit(x);} }
int query(int x) {//最长不下降
int mxx = -1;
while(x) {
mxx = max(ft[x], mxx);
x -= lowbit(x);
}
return mxx;
}
int main() {
// freopen("binary13.in", "r", stdin);
// freopen("binary5.out", "w", stdout);
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
int fa, ch;
for(int i = 2; i <= n; i++) {
scanf("%d%d",&fa, &ch);
if(ch == 0) lch[fa] = i;
else rch[fa] = i;
}
dfs(1);
// for(int i = 1; i <= tot; i++) printf("%d ", b[i]);
// printf("\n");
for(int i = 1; i <= tot; i++) c[i] = a[b[i]], c[i] -= i, mn = min(mn, c[i]);
for(int i = 1; i <= tot; i++) {
c[i] = c[i] - mn + 1;//都变成大于等于1的, 才能用树状数组做
mx = max(c[i], mx);//找树状数组下标最大值
}
// for(int i = 1; i <= tot; i++) printf("%d ", c[i]);
ans = -1;
for(int i = 1; i <= tot; i++) {
ft[c[i]] = query(c[i]) + 1;
ans = max(ft[c[i]], ans);
add(c[i], ft[c[i]]);
}
printf("%d", tot - ans);//“最长不下降”是要保留下来的
}
正确代码: 二分
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=100000+20;
int n,p[maxn],lch[maxn],rch[maxn];
int order[maxn],tot=0;
int f[maxn],ans;
inline void read(int& n){
n=0;
char ch=getchar();
while(ch<'0' || ch>'9') ch=getchar();
do{
n=n*10+ch-'0';
ch=getchar();
}while(ch>='0' && ch<='9');
return;
}
void init(){
memset(lch,-1,sizeof(lch));
memset(rch,-1,sizeof(rch));
read(n);
for(int i=1;i<=n;i++) read(p[i]);
for(int i=2;i<=n;i++){
int fa,ff;
read(fa);
read(ff);
if(ff==0) lch[fa]=i;
else rch[fa]=i;
}
return;
}
void dfs(int node){
if(node==-1) return;
dfs(lch[node]);
++tot;
order[tot]=p[node]-tot;
dfs(rch[node]);
return;
}
void solve(){
dfs(1);
for(int i=1;i<=tot;i++){
f[i]=2100000000;
}
f[1]=order[1];ans=1;
for(int i=2;i<=tot;i++){
if(order[i]>=f[ans])
f[++ans]=order[i];
else{
int l = 1,r = ans, xxx;//注意右边界为r
while (l <= r) {
int mid = (l + r) >> 1;
if (f[mid] < order[i]) {
l = mid + 1;
} else {
xxx = mid;
r = mid - 1;
}
}
f[xxx] = order[i];
}
}
ans=n-ans;
printf("%d",ans);
return;
}
int main(){
init();
solve();
return 0;
}
数字对
【题目描述】
小 H 是个善于思考的学生,现在她又在思考一个有关序列的问题。
她的面前浮现出一个长度为 n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= n)。
这个特殊区间满足,存在一个 k(L <= k <= R),并且对于任意的 i(L <= i <= R),ai 都能
被 ak 整除。这样的一个特殊区间 [L, R]价值为 R - L。
小 H 想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢?这些
区间又分别是哪些呢?你能帮助她吧。
【输入格式】
第一行,一个整数 n.
第二行,n个整数,代表 ai.
【输出格式】
第一行两个整数,num和 val,表示价值最大的特殊区间的个数以及最大价值。
第二行 num 个整数,按升序输出每个价值最大的特殊区间的 L.
【样例输入 1】
5
4 6 9 3 6
【样例输出 1】
1 3
2
【样例输入 2】
5
2 3 5 7 11
【样例输出 2】
5 0
1 2 3 4 5
【数据范围】
30%: 1 <= n <= 30 , 1 <= ai <= 32.
60%: 1 <= n <= 3000 , 1 <= ai <= 1024.
80%: 1 <= n <= 300000 , 1 <= ai <= 1048576.
100%: 1 <= n <= 500000 , 1 <= ai < 2 ^ 31.
分析
等下再具体的打...
RMQ的思想, 求区间gcd和最小值, 二分找答案
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 500000+9;
inline int gcd(int x, int y) {return !y ? x : gcd(y, x%y);}
int n;
int f[N][20], g[N][20];
void init() {
for(int k = 1; (1<<k) <= n; k++) {
for(int i = 1; i+(1<<k)-1 <= n; i++) {
f[i][k] = min(f[i][k-1], f[i+(1<<(k-1))][k-1]);
g[i][k] = gcd(g[i][k-1], g[i+(1<<(k-1))][k-1]);
}
}
}
int RMQ_gcd(int l, int r) {
int m = r - l + 1;
int k = 0;
while(1<<k <= m) k++;
k--;
return gcd(g[l][k], g[r-(1<<k)+1][k]);
}
int RMQ(int l, int r) {
int m = r - l + 1;
int k = 0;
while(1<<(k+1) <= m) k++;
return min(f[l][k], f[r-(1<<k)+1][k]);
}
int num;
int ans[N], tot;
int check(int Len) {
int r, is = 0;
for(int l = 1; l <= n && l + Len - 1 <= n; l++) {
r = l+Len-1;
if(RMQ(l, r) == RMQ_gcd(l, r)) {
if(is == 0) tot = 0;
is = 1;
ans[++tot] = l;
}
}
return is;
}
int main() {
// freopen("pair.in", "r", stdin);
// freopen("pair.out", "w", stdout);
scanf("%d", &n);
for(int i = 1; i <= n; i++) scanf("%d", &f[i][0]), g[i][0] = f[i][0];
init();
int l = 1, r = n, mid, Len;
while(l <= r) {//左闭右闭
mid = (l+r)>>1;
if(check(mid)) {
Len = mid;
l = mid+1;
num = tot;
} else {
r = mid - 1;
}
}
printf("%d %d\n", num, Len - 1);
for(int i = 1; i <= tot; i++) printf("%d ",ans[i]);
}
/*
7
6 3 9 18 4 8 2
*/
【oi模拟赛】长乐中学-不知道多少年的更多相关文章
- 【前行】◇第3站◇ 国庆训练营·OI制模拟赛
[第3站] 国庆训练营·OI制模拟赛Ⅰ 怀着冲刺提高组400的愿望来到这个very small but very interesting 的训练营QwQ 在北大dalao的带领下开始了第一场OI模拟赛 ...
- Nescafe #29 NOIP模拟赛
Nescafe #29 NOIP模拟赛 不知道这种题发出来算不算侵权...毕竟有的题在$bz$上是权限题,但是在$vijos$似乎又有原题...如果这算是侵权的话请联系我,我会尽快删除,谢谢~ 今天开 ...
- [OI笔记]NOIP2017前(退役前)模拟赛的总结
好久没写blog了- 在noip2017前的最后几天,也就是在我可能将要AFO的前几天写点东西吧- 记录这最后几个月打的那些大大小小的模拟赛 一些比赛由于不允许公开所以就没有贴链接跟题面了- 2017 ...
- 2019中山纪念中学夏令营-Day9[JZOJ](第六次模拟赛)
Begin (题目的排序方式:Unkown其实是按心情排的) 异或:(摘自百度百科) 异或(xor)是一个数学运算符.它应用于逻辑运算.异或的数学符号为“⊕”,计算机符号为“xor”.其运算法则为: ...
- 2014-11-2 NOIP模拟赛1
Noip2009 团结模拟赛如题目理解困难,请自行阅读或参考样例.内存限制均为 256MB,时间限制均为 1s.出题人不会 故意 在题目中设置陷阱,但请自己注意程序的正确性.IO 文件名(.in/.o ...
- 冲刺$\mathfrak{CSP-S}$集训模拟赛总结
开坑.手懒并不想继续一场考试一篇文. 既没必要也没时间侧边栏的最新随笔题解反思相间也丑 而且最近越来越懒了竟然都不写题解了……开坑也是为了督促自己写题解. 并不想长篇大论.简要题解也得写啊QAQ. 目 ...
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- CH Round #48 - Streaming #3 (NOIP模拟赛Day1)
A.数三角形 题目:http://www.contesthunter.org/contest/CH%20Round%20%2348%20-%20Streaming%20%233%20(NOIP模拟赛D ...
- 3.27模拟赛 sutoringu(后缀数组)
\(\color{white}{mjt是机房模拟赛独自切过题的唯一的人...}\) (应本人要求删掉惹) \(Description\) 给你\(n,k\)和长为\(n\)的字符串\(s\).一个区间 ...
随机推荐
- 【解决】Failed to restart network.service: Unit network.service not found.
问题:使用systemctl restart network 或 service network restart 命令重启网卡失败. 分析:原因其实也很简单,命令用错了,造成了找不到相应的网卡服务. ...
- python函数编程-装饰器decorator
函数是个对象,并且可以赋值给一个变量,通过变量也能调用该函数: >>> def now(): ... print('2017-12-28') ... >>> l = ...
- 开启Hyper-V
开启Hyper-V 添加方法非常简单,把以下内容保存为.cmd文件,然后以管理员身份打开这个文件.提示重启时保存好文件重启吧,重启完成就能使用功能完整的Hyper-V了. pushd "%~ ...
- Vue 中的keep-alive 什么用处?
keep-alive keep-alive是Vue提供的一个抽象组件,用来对组件进行缓存,从而节省性能,由于是一个抽象组件,所以在v页面渲染完毕后不会被渲染成一个DOM元素 <keep-aliv ...
- bayaim_Centos7.6_mysql源码5.7-多my.cnf_20190424.txt
用户名/密码mysql/mysql 一.安装mysql: 位置位于 /data/mysql 如果遇到依赖,无法删除,使用 rpm -e --nodeps <包的名字> 不检查依赖,直接删除 ...
- Where is the kernel documentation?; Ubuntu 上如何安装 linux 内核文档;fedora 上如何安装linux内核文档?
有时候,linux内核文档对我们很重要,我们可以在linux系统中安装,并及时查看: 参考链接:https://askubuntu.com/questions/841043/where-is-the- ...
- MATLAB实例:散点密度图
MATLAB实例:散点密度图 作者:凯鲁嘎吉 - 博客园http://www.cnblogs.com/kailugaji/ MATLAB绘制用颜色表示数据密度的散点图 数据来源:MATLAB中“fit ...
- 31.Java基础_日期/日期格式/日历类
Date类 Date对象构造方法 Date对象常用方法 import java.util.*; public class test { public static void main(String[] ...
- 划分为k个相等的子集
给定一个整数数组 nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等. 示例 1: 输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4 ...
- [译]Vulkan教程(12)图形管道基础之入门
[译]Vulkan教程(12)图形管道基础之入门 Introduction 入门 Over the course of the next few chapters we'll be setting u ...