您的位置:首页 > 其它

(蓝桥杯备战)(数位bfs)与完全二叉树,st表

2020-04-02 18:36 120 查看

蓝桥杯第十一届校内模拟赛的所学
3. 叶节点数

【问题描述】
一棵包含有2019个结点的二叉树,最多包含多少个叶结点?
【答案提交】
这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分

对任何一棵二叉树:度为0的结点数(即叶节点) = 度为2的节点数 + 1;
当二叉树的总个数为奇数时,此二叉树"无度为1"的结点
当二叉树的总个数为偶数时,此二叉树"只有一个度为1"的结点
设:度为2的结点数为n个
度为0的结点数+度为1的结点数+度为2的结点数=N
( n+1 )+(n)=2019
解得:n=1009
所以 :
度为2的结点数:1009个
度为1的结点数:0个(因为2019是奇数,所以此二叉树没有度为1的结点)
度为0的结点数(叶子节点数):1010个(等于度为2的结点数+1)

##编程题(二)
问题描述

在数列 a[1],a[2],…,a

中,如果对于下标 i,j,k 满足 0<i<j<k<n+1 且 a[i]<a[j]<a[k],则称 a[i],a[j],a[k] 为一组递增三元组,a[j]

为递增三元组的中心。

给定一个数列,请问数列中有多少个元素可能是递增三元组的中心。
输入格式

输入的第一行包含一个整数 n

第二行包含 n
个整数 a[1],a[2],…,a

,相邻的整数间用空格分隔,表示给定的数列。
输出格式

输出一行包含一个整数,表示答案。
评测用例规模与约定

对于 50
的评测用例,2<=n<=100,0<=Num<=1000 。
对于所有评测用例,2<=n<=1000,0<=Num<=10000
当然也可以用 ST 表把复杂度优化为 O(nlogn)
以后学st表

代码如下:

#include <bits/stdc++.h>
#define MAXN 10007
#define INF 0x3f3f3f3f
using namespace std;
int n,ans,t1[MAXN][20],t2[MAXN][20];
inline void init() {
for (int j=1;j<=log2(n);j++)
for (int i=1;i<=n-(1<<j)+1;i++) {
t1[i][j]=min(t1[i][j-1],t1[i+(1<<(j-1))][j-1]);
t2[i][j]=max(t2[i][j-1],t2[i+(1<<(j-1))][j-1]);
}
}
inline int q1(int l,int r) {
if (l>r) return INF;
int t=log2(r-l+1);
return min(t1[l][t],t1[r-(1<<t)+1][t]);
}
inline int q2(int l,int r) {
if (l>r) return -1;
int t=log2(r-l+1);
return max(t2[l][t],t2[r-(1<<t)+1][t]);
}
int main() {
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&t1[i][0]),t2[i][0]=t1[i][0];
init();
for (int i=1;i<=n;i++)
if (q1(1,i-1)<t1[i][0] && q2(i+1,n)>t1[i][0]) ans++;
printf("%d",ans);
}

##编程题(三)
问题描述

一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的数,例如 1135
是一个数位递增的数,而 1024

不是一个数位递增的数。

给定正整数 n
,请问在整数 1 至 n

中有多少个数位递增的数?
输入格式

输入的第一行包含一个整数 n


输出格式

输出一行包含一个整数,表示答案。
评测用例规模与约定

对于 40%
的评测用例,1<=n<=1000。
对于 80% 的评测用例,1<=n<=100000。
对于所有评测用例,1<=n<=1000000

——————————————————————————————

#include <bits/stdc++.h>
int n,ans=0;
using namespace std;
void dfs(int num) {
for (int i=num%10?num%10:1;i<=9;i++)
if (num*10+i<=n) ans++,dfs(num*10+i);//几行代码精辟
}
int main() {
scanf("%d",&n),dfs(0);
printf("%d",ans);
return 0;
}

我既没看出来这是dp也没看出是深度搜索
##编程题(五)
问题描述

小明想知道,满足以下条件的正整数序列的数量:

第一项为 n


第二项不超过 n

;
从第三项开始,每一项小于前两项的差的绝对值。

请计算,对于给定的 n

,有多少种满足条件的序列。
输入格式

输入一行包含一个整数 n


输出格式

输出一个整数,表示答案。答案可能很大,请输出答案除以 10000

的余数。
评测用例规模与约定

对于 20%
的评测用例,1<=n<=5。
对于 50% 的评测用例,1<=n<=10。
对于 80% 的评测用例,1<=n<=100。
对于所有评测用例,1<=n<=1000

——————————————————————————————

50
分的做法就是直接暴力 dfs,首先敲了如下代码,再进行优化。
这东西能过%50,但是老子不会!!!

#include <bits/stdc++.h>
#define MAXN 1007
using namespace std;
int ans,a[100007];
int dfs(int st) {
ans++;
int cha=abs(a[st]-a[st-1]);
for (int i=1;i<cha;i++) {
a[st+1]=i,dfs(st+1);
}
}
int main() {
int n;
scanf("%d",&n),a[1]=n;
for (int i=1;i<=n;i++) {
a[2]=i,dfs(2);
}
printf("%d",ans);
return 0;
}

靠!离省一太远了这东西我根本不会,我一天天都在干什么

#include <bits/stdc++.h>
#define MAXN 1007
#define mod 10000
using namespace std;
int ans,f[MAXN][MAXN];
int dfs(int p1,int p2) {
if (f[p1][p2]) return f[p1][p2];
f[p1][p2]=1;
for (int i=1;i<abs(p1-p2);i++)
f[p1][p2]+=dfs(p2,i),f[p1][p2]%=mod;
return f[p1][p2];
}
int main() {
freopen("","w",stdout);
printf("int table[1001]={0,");
for (int n=1;n<=1000;n++) {
ans=0;
for (int i=1;i<=n;i++)
ans+=dfs(n,i),ans%=mod;
printf("%d",ans);
if (n!=1000) printf(",");
}
printf("}");
return 0;
}

##编程题(六)
问题描述

小明要组织一台晚会,总共准备了 n
个节目。然后晚会的时间有限,他只能最终选择其中的 m

个节目。

这 n

个节目是按照小明设想的顺序给定的,顺序不能改变。

小明发现,观众对于晚上的喜欢程度与前几个节目的好看程度有非常大的关系,他希望选出的第一个节目尽可能好看,在此前提下希望第二个节目尽可能好看,依次类推。

小明给每个节目定义了一个好看值,请你帮助小明选择出 m

个节目,满足他的要求。
输入格式

输入的第一行包含两个整数 n
, m

,表示节目的数量和要选择的数量。

第二行包含 n

个整数,依次为每个节目的好看值。
输出格式

输出一行包含 m

个整数,为选出的节目的好看值。
评测用例规模与约定

对于 30%
的评测用例,1<=n<=20;
对于 60% 的评测用例,1<=n<=100;
对于所有评测用例,1<=n<=100000,0<=value<=100000

——————————————————————————————

一个贪心题。

由于在小明的策略下一定是要选择当前能选中好看值最大的节目,所以每次选择就是在当前能选的节目中找好看值最大的,不考虑之后如何选择。

当然小明至少要给未选节目们留最小的选择空间,不然就无法选够 m

个节目,

于是发现当前能选的节目是一个区间,比如小明还有 p
个节目要选,共 n 个节目,上次选了 k

号节目。

那么他的本次选择节目区间就是 [k+1,n−p+1]

,如此迭代,就可以确定每次的选择。

对于 60
分来说每次在区间内容找最大值即可,优化的话就是加入记录了最大值和最大值来源 ST

表(我们同时关心这两个值)。

还要注意如果区间上有多个值相等,应该保留位置靠前的一个(贪心)。
有是St表靠必须干了
#include <bits/stdc++.h>
#define MAXN 100007
using namespace std;
struct Seg { int val,id; }st[MAXN][20];
int n,m,k,v[MAXN];
inline void init() {
for (int j=1;j<=log2(n);j++)
for (int i=1;i<=n-(1<<j)+1;i++) {
if (st[i][j-1].val<st[i+(1<<(j-1))][j-1].val)
st[i][j]=st[i+(1<<(j-1))][j-1];
else st[i][j]=st[i][j-1];
}
}
inline Seg q(int l,int r) {
int t=log2(r-l+1);
if (st[l][t].val>=st[r-(1<<t)+1][t].val) return st[l][t];
else return st[r-(1<<t)+1][t];
}
int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&st[i][0].val),st[i][0].id=i;
init(),k=1;
for (int i=m;i>=1;i–) {
Seg now=q(k,n-i+1);
k=now.id+1,printf("%d ",now.val);
}
return 0;
}

  • 点赞
  • 收藏
  • 分享
  • 文章举报
mrgaohaihang 发布了23 篇原创文章 · 获赞 1 · 访问量 503 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: