蓝桥小小结
创始人
2025-06-01 16:17:24
0

100. 增减序列

给定一个长度为 n 的数列 a1,a2,…,an,每次可以选择一个区间 [l,r],使下标在这个区间内的数都加一或者都减一

求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。

分析

  • 因为终态所有数都一样,所以最后差分数组一定是 b [1] = 一个常数,b [2]-b [n] 都等于 0 (求数列种数的时候也可以使用)

  • 差分数组数组的操作 b [l] += 1,b [r+1] -= 1 的特性可以使正负两个数相消,所以最后差分就只剩同符号的数,此时操作数为 min (pos,neg) //pos 为差分数组中正数和 neg为负数和的绝对值

  • b [1] 的操作次数也就是种类数量。想到数列的值就是 b [1] 的值 操作有对b[1]和b[n+1]等价,eg 假设一开始 b [1] 为 2,abs (pos-neg) 为 3,b [1] 的取值可能为 2,3,4,5,即 abs (pos-neg)+1

方案一 b [1] += 1,b [i+1] -=1;
方案二 b [i] -= (-1),b [n+1] += (-1);
等价

ps.
差分:差分与前缀和相对,可以视为前缀和的逆运算。差分它可以维护多次对序列的一个区间修改一个数。

“区间修改+单点查询”,用差分数组往往不够用。因为差分数组对“区间修改”很高效,但是对“单点查询”并不高效。此时需要用树状数组和线段树来求解

code:

#include
#include
using namespace std;
const int N = 100010;
#define ll long long 
ll a[N];
ll b[N];
int main(){ll n;cin >> n;for(ll i=1;i<=n;i++){cin >> a[i];b[i] = a[i] - a[i-1];     // b数组为差分数组}ll pos=0,neg=0;for(ll i=2;i<=n;i++){if(b[i] > 0) pos += b[i];else neg -= b[i];         // 相当于取绝对值}ll ans1,ans2;ans1 = min(neg,pos) + abs(pos-neg);ans2 = abs(pos-neg)+1;cout << ans1 << endl << ans2;
}作者:chen_
链接:https://www.acwing.com/file_system/file/content/whole/index/content/8274441/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1460. 我在哪?

约翰想要知道最小的 K 的值,使得他查看任意连续 K个邮箱序列,他都可以唯一确定这一序列在道路上的位置。

例如,假设沿路的邮箱序列为 ABCDABC 。

约翰不能令 K=3,因为如果他看到了 ABC,则沿路有两个这一连续颜色序列可能所在的位置。

最小可行的 K 的值为 K=4,因为如果他查看任意连续 4 个邮箱,那么可得到的连续颜色序列可以唯一确定他在道路上的位置

分析

最小不重复连续子串

STL哈希+二分查找
***** 使用二分查找只要满足二段性即可,不一定非得要有序

长度具有单调性:
因为越长,子串区分度就越大
如果长度为i不行,那么i-1肯定也不行,反之i行,i+1肯定也行,具有二段性

#include 
#include 
#include 
#include 
using namespace std;
int n;
string str;
unordered_set S;
bool check(int mid){S.clear();for (int i = 0; i + mid - 1 < n; i ++ ){string s = str.substr(i, mid);if (S.count(s)) return false;// 已经存在的s字符串个数大于1S.insert(s);}return true;
}int main(){cin >> n >> str;int l = 1, r = n;while (l < r){   // 对长度进行二分int mid = l + r >> 1;if (check(mid)) r = mid;else l = mid + 1;}cout << r << endl;return 0;
}作者:yxc
链接:https://www.acwing.com/activity/content/code/content/5509029/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

ps.
字符串哈希: https://www.cnblogs.com/moyujiang/p/11213535.html
后缀数组:https://www.cnblogs.com/zwfymqz/p/8413523.html#_labelTop


1497. 树的遍历

给出树的后序遍历和中序遍历,输出层序遍历

输入样例:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

输出样例:

4 1 6 3 5 7 2

code

#include
#include
#include
#include
#includeusing namespace std;const int N = 35;int n;
int a[N],b[N],p[N];
int l[N],r[N];int build(int al,int ar,int bl,int br,int d){if(al > ar) return 0;int val = a[ar];int k = p[val];l[val] = build(al,al+k-1-bl,bl,k-1,d+1);r[val] = build(al+k-bl,ar-1,k+1,br,d+1);return val;
}void bfs(){queue q;q.push(a[n-1]);while(q.size()){int t = q.front();q.pop();cout << t << " ";if(l[t]) q.push(l[t]);if(r[t]) q.push(r[t]);}
}int main(){cin >> n;for(int i=0;i> a[i];for(int i=0;i> b[i];for(int i=0;i

一棵二叉树可由它的中序遍历和后序遍历确定
这是因为:
1.后序遍历的最后一定是该树或子树的根
2.中序遍历根的左右分左子树和右子树

层序遍历是一个bfs的过程

ps. 给出树的后序遍历和中序遍历,输出后序遍历

#include
#include
using namespace std;
const int N = 10010;
char a[N],b[N];   // a->前序   b->中序
int idx;
void build(int l,int r){if(l > r) return;int u = strchr(b,a[idx])-b;  //a[idx]在 b数组的下标位置 idx++;build(l,u-1);     // 左子树区间 build(u+1,r);     // 右子树区间cout << b[u]; 
} 
int main(){scanf("%s%s",&a,&b);build(0,strlen(a)-1);return 0;
}

2058. 笨拙的手指

每当贝茜将数字转换为一个新的进制并写下结果时,她总是将其中的某一位数字写错。

例如,如果她将数字 14转换为二进制数,那么正确的结果应为 1110,但她可能会写下 0110 或 1111。

贝茜不会额外添加或删除数字,但是可能会由于写错数字的原因,写下包含前导 0的数字。

给定贝茜将数字 N转换为二进制数字以及三进制数字的结果(即各其中一位是错误的),请确定 N 的正确初始值(十进制表示)。

分析

如何在不同进制之间转换数字
可以用秦九韶算法将b进制转换为十进制

// 将b进制的数转化成十进制
int get(string s, int b)
{int res = 0;// 秦九韶算法:每次将前面的数向高位移动一位,即*b,然后加上当前个位数,即+cfor (auto c: s)res = res * b + c - '0';return res;
}

code

#include 
#include 
#include 
#include   using namespace std;int base(string s,int b){int res = 0;for(auto x:s){  //枚举s的每一位res = res*b+x-'0';}return res;
}int main(){string x,y;cin >> x >> y;unordered_set hash;for(int i=0;istring s = x;s[i] ^= 1;if(s.size()>1 && s[0]=='0') continue;// 因为原先的字符串s的首个位置不可能为0hash.insert(base(s,2));}for(int i=0;ifor(int j=0;j<3;j++){if(y[i]-'0'!=j){string s = y;s[i] = j+'0';if(s.size()>1 && s[0]=='0') continue;int n=base(s,3);if(hash.count(n))cout << n << endl;}}}return 0;
}

3555. 二叉树

给定一个 n 个结点(编号 1∼n)构成的二叉树,其根结点为 1号点。

进行 m次询问,每次询问两个结点之间的最短路径长度。

树中所有边长均为 1。

分析

LCA问题

对于任意两个结点, 它们之间的最短距离会等于两个结点与它们的最近公共祖先之间的深度差之和

先把两个结点调整到同一深度, 然后同时往上走, 直到两个结点相等。
要完成这些, 除了记录左右儿子, 还要记录父节点以及各结点深度。

  • 朴素做法
    维护x1为较深的那个,x1往上走, 直到与x2深度相同,同时往上走, 直到两结点相同
    时间复杂度:

遍历树获取深度 O(n)
你们获取祖先 O(logn)

#include 
#include 
#include using namespace std;const int N = 1010;
int n,m,res;
int father[N];
int L[N],R[N];int find(int x,int a[]){int k=0;while(x!=1){a[k++] = x;x = father[x];}a[k++] = 1;   // 数组a来存储路径return k;     // k为个数
}int main(){int T;cin >> T;while(T--){cin >> n >> m;for(int i=1;i<=n;i++){int x,y;cin >> x >> y;if(x != -1) father[x] = i;if(y != -1) father[y] = i;}while(m--){int l,r;cin >> l >> r;int x = find(l,L);int y = find(r,R);// 朴素做法                             for(int i=x-1,j=y-1;i>=0 && j>=0;i--,j--){if(L[i] == R[j]){    // 到达相同的节点x--,y--;         // -2}else break;}cout << x+y << endl;}}
}

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...