
AcWing算法基础
基础算法与数据结构的原理,并给出相应 代码模板
<Running Snail>
奇点将至
展开
-
AcWing 103. 电影
题目莫斯科正在举办一个大型国际会议,有n个来自不同国家的科学家参会。每个科学家都只懂得一种语言。为了方便起见,我们把世界上的所有语言用1到109之间的整数编号。在会议结束后,所有的科学家决定一起去看场电影放松一下。他们去的电影院里一共有m部电影正在上映,每部电影的语音和字幕都采用不同的语言。对于观影的科学家来说,如果能听懂电影的语音,他就会很开心;如果能看懂字幕,他就会比较开心;如果全都不懂,他就会不开心。现在科学家们决定大家看同一场电影。请你帮忙选择一部电影,可以让观影很开心的人最多。如原创 2020-09-30 23:19:18 · 323 阅读 · 0 评论 -
AcWing 102. 最佳牛围栏
题目农夫约翰的农场由 N 块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头。约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。围起区域内至少需要包含 F 块地,其中 F 会在输入中给出。在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。输入格式第一行输入整数 N 和 F ,数据间用空格隔开。接下来 N 行,每行输入一个整数,第i+1行输入的整数代表第i片区域内包含的牛的数目。输出格式输出原创 2020-09-30 23:16:12 · 378 阅读 · 0 评论 -
Java第二章
2.15import java.util.Scanner;public class book { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Enter x1 and y1:"); double x1 = input.nextDouble(); double y1 = in原创 2020-09-30 22:24:36 · 113 阅读 · 0 评论 -
AcWing 101. 最高的牛
题目有 N 头牛站成一行,被编队为1、2、3…N1、2、3…N1、2、3…N,每头牛的身高都为整数。当且仅当两头牛中间的牛身高都比它们矮时,两头牛方可看到对方。现在,我们只知道其中最高的牛是第 P 头,它的身高是 H ,剩余牛的身高未知。但是,我们还知道这群牛之中存在着 M 对关系,每对关系都指明了某两头牛 A 和 B 可以相互看见。求每头牛的身高的最大可能值是多少。输入格式第一行输入整数N,P,H,M,N,P,H,M,N,P,H,M,数据用空格隔开。接下来M行,每行输出两个整数 A 和 B原创 2020-09-30 00:22:33 · 308 阅读 · 0 评论 -
AcWing 100. 增减序列
题目给定一个长度为 n 的数列 a1,a2,…,ana_1,a_2,…,a_na1,a2,…,an,每次可以选择一个区间 [l,r],使下标在这个区间内的数都加一或者都减一。求至少需要多少次操作才能使数列中的所有数都一样,并求出在保证最少次数的前提下,最终得到的数列可能有多少种。输入格式第一行输入正整数n。接下来n行,每行输入一个整数,第i+1行的整数代表aia_iai。输出格式第一行输出最少操作次数。第二行输出最终能得到多少种结果。数据范围0<n≤1050<n≤10原创 2020-09-30 00:11:57 · 252 阅读 · 0 评论 -
AcWing 898. 数字三角形
题目给定一个如下图所示的数字三角形,从顶部出发,在每一结点可以选择移动至其左下方的结点或移动至其右下方的结点,一直走到底层,要求找出一条路径,使路径上的数字的和最大。 7 3 8 8 1 0 2 7 4 44 5 2 6 5输入格式第一行包含整数n,表示数字三角形的层数。接下来n行,每行包含若干整数,其中第 i 行表示数字三角形第 i 层包含的整数。输出格式输出一个整数,表示最大的路径数字和。数据范围1≤n≤原创 2020-09-30 00:00:58 · 357 阅读 · 0 评论 -
AcWing 1057. 股票买卖 IV
题目给定一个长度为 N 的数组,数组中的第 i 个数字表示一个给定股票在第 i 天的价格。设计一个算法来计算你所能获取的最大利润,你最多可以完成 k 笔交易。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。一次买入卖出合为一笔交易。输入格式第一行包含整数 N 和 k,表示数组的长度以及你可以完成的最大交易数量。第二行包含 N 个不超过 100001000010000 的正整数,表示完整的数组。输出格式输出一个整数,表示最大利润。数据范围1≤N≤1051≤N≤10^51原创 2020-09-28 23:44:29 · 189 阅读 · 0 评论 -
AcWing 1058. 股票买卖 V
题目给定一个长度为 N 的数组,数组中的第 i 个数字表示一个给定股票在第 i 天的价格。设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。输入格式第一行包含整数 N,表示数组长度。第二行包含 N 个不超过 100001000010000 的正整数,表示完整的数组。输出格式输出一个整数,表示最大利润。数据范围1≤N≤原创 2020-09-28 23:39:24 · 206 阅读 · 0 评论 -
AcWing 1056. 股票买卖 III
题目给定一个长度为 NNN 的数组,数组中的第 iii 个数字表示一个给定股票在第 iii 天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成两笔交易。注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。输入格式第一行包含整数 N,表示数组长度。第二行包含 N 个不大于 10910^9109的正整数,表示完整的数组。输出格式输出一个整数,表示最大利润。数据范围1≤N≤1051≤N≤10^51≤N≤105输入样例1:83 3 5 0 0 3 1 4输原创 2020-09-28 23:33:51 · 129 阅读 · 0 评论 -
AcWing 1055. 股票买卖 II
题目给定一个长度为 NNN 的数组,数组中的第 iii 个数字表示一个给定股票在第 iii天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。输入格式第一行包含整数 N,表示数组长度。第二行包含 N 个不大于 100001000010000 的正整数,表示完整的数组。输出格式输出一个整数,表示最大利润。数据范围1≤N≤1051≤N≤10^51≤N≤105输入样例1:6原创 2020-09-28 23:27:45 · 136 阅读 · 0 评论 -
AcWing 1054. 股票买卖
题目给定一个长度为 NNN的数组,数组中的第 iii个数字表示一个给定股票在第 iii 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。注意你不能在买入股票前卖出股票。输入格式第一行包含整数 N,表示数组长度。第二行包含 N 个不大于 10910^9109 的正整数,表示完整的数组。输出格式输出一个整数,表示最大利润。数据范围1≤N≤1051≤N≤10^51≤N≤105,输入样例1:67 1 5 3 6 4输出样例1:5原创 2020-09-28 23:20:20 · 170 阅读 · 0 评论 -
AcWing(状态机模型) 1049. 大盗阿福
题目描述阿福是一名经验丰富的大盗。趁着月黑风高,阿福打算今晚洗劫一条街上的店铺。这条街上一共有 NNN 家店铺,每家店中都有一些现金。阿福事先调查得知,只有当他同时洗劫了两家相邻的店铺时,街上的报警系统才会启动,然后警察就会蜂拥而至。作为一向谨慎作案的大盗,阿福不愿意冒着被警察追捕的风险行窃。他想知道,在不惊动警察的情况下,他今晚最多可以得到多少现金?输入格式输入的第一行是一个整数 TTT,表示一共有 T 组数据。接下来的每组数据,第一行是一个整数NNN ,表示一共有NNN 家店铺。第二行原创 2020-09-28 23:07:17 · 246 阅读 · 0 评论 -
~~朴素dijkstra算法 (搜索与图论)(附模板题AcWing 849. Dijkstra求最短路 I)
模板时间复杂是 O(n2+m), n表示点数,m 表示边数int g[N][N]; // 存储每条边int dist[N]; // 存储1号点到每个点的最短距离bool st[N]; // 存储每个点的最短路是否已经确定// 求1号点到n号点的最短路,如果不存在则返回-1int dijkstra(){ memset(dist, 0x3f, sizeof dist); dist[1] = 0; for (int i = 0; i < n - 1; i +原创 2020-05-10 19:24:31 · 353 阅读 · 0 评论 -
C++STL常用简洁版
vector, 变长数组,倍增的思想 size() 返回元素个数 empty() 返回是否为空 clear() 清空 front()/back() push_back()/pop_back() begin()/end() [] 支持比较运算,按字典序pair<int, int> first, 第一个元素 second, 第二个元素 支持比较运算,以first为第一关键字,以second为第二关键字(原创 2020-05-09 21:30:36 · 310 阅读 · 1 评论 -
~~字符串哈希(数据结构)(附模板题AcWing 841 字符串哈希)
核心思想:将字符串看成P进制数,P的经验值是131或13331,取这两个值的冲突概率低。小技巧:取模的数用2^64,这样直接用unsigned long long存储,溢出的结果就是取模的结果。typedef unsigned long long ULL;ULL h[N], p[N]; // h[k]存储字符串前k个字母的哈希值, p[k]存储 P^k mod 2^64// 初始化p[0] = 1;for (int i = 1; i <= n; i ++ ){ h[i] =原创 2020-05-09 21:27:30 · 279 阅读 · 0 评论 -
~~一般哈希(数据结构)(附模板题AcWing 840 模拟散列表)
(1) 拉链法int h[N], e[N], ne[N], idx;// 向哈希表中插入一个数void insert(int x){ int k = (x % N + N) % N; e[idx] = x; ne[idx] = h[k]; h[k] = idx ++ ;}// 在哈希表中查询某个数是否存在bool find(int x){ int k = (x % N + N) % N; for (int i = h[k]; i != -1原创 2020-05-09 18:31:27 · 320 阅读 · 0 评论 -
~~堆(数据结构)(附模板题 AcWing 838. 堆排序)
模板// h[N]存储堆中的值, h[1]是堆顶,x的左儿子是2x, 右儿子是2x + 1// ph[k]存储第k个插入的点在堆中的位置// hp[k]存储堆中下标是k的点是第几个插入的int h[N], ph[N], hp[N], size;// 交换两个点,及其映射关系void heap_swap(int a, int b){ swap(ph[hp[a]],ph[hp[b]]); swap(hp[a], hp[b]); swap(h[a], h[b]);}v原创 2020-05-09 18:20:58 · 461 阅读 · 0 评论 -
~~并查集模板(数据结构)(附题目AcWing 836. 合并集合)
(1)朴素并查集: int p[N]; //存储每个点的祖宗节点 // 返回x的祖宗节点 int find(int x) { if (p[x] != x) p[x] = find(p[x]); return p[x]; } // 初始化,假定节点编号是1~n for (int i = 1; i <= n; i ++ ) p[i] = i; // 合并a和b所在的两个集合: p[find(a)]原创 2020-05-09 18:14:56 · 291 阅读 · 0 评论 -
~~Trie树(数据结构)(附题目:AcWing 835. Trie字符串统计)
模板int son[N][26], cnt[N], idx;// 0号点既是根节点,又是空节点// son[][]存储树中每个节点的子节点// cnt[]存储以每个节点结尾的单词数量// 插入一个字符串void insert(char *str){ int p = 0; for (int i = 0; str[i]; i ++ ) { int u = str[i] - 'a'; if (!son[p][u]) son[p][u] = +原创 2020-05-09 08:56:28 · 263 阅读 · 0 评论 -
~~KMP(数据结构)
模板// s[]是长文本,p[]是模式串,n是s的长度,m是p的长度求模式串的Next数组:for (int i = 2, j = 0; i <= m; i ++ ){ while (j && p[i] != p[j + 1]) j = ne[j]; if (p[i] == p[j + 1]) j ++ ; ne[i] = j;}// 匹配for (int i = 1, j = 0; i <= n; i ++ ){ while (原创 2020-05-09 08:52:26 · 179 阅读 · 0 评论 -
~~单调队列(数据结构)(附题目)
模板常见模型:找出滑动窗口中的最大值/最小值int hh = 0, tt = -1;for (int i = 0; i < n; i ++ ){ while (hh <= tt && check_out(q[hh])) hh ++ ; // 判断队头是否滑出窗口 while (hh <= tt && check(q[tt], i)) tt -- ; q[ ++ tt] = i;}题目举例给定一个大小为n≤106的数组原创 2020-05-09 08:50:33 · 870 阅读 · 0 评论 -
~~单调栈(数据结构)
模板常见模型:找出每个数左边离它最近的比它大/小的数int tt = 0;for (int i = 1; i <= n; i ++ ){ while (tt && check(stk[tt], i)) tt -- ; stk[ ++ tt] = i;}原创 2020-05-09 08:46:49 · 292 阅读 · 0 评论 -
~~队列(数据结构)(附模板题 AcWing 829. 模拟队列)
1. 普通队列:// hh 表示队头,tt表示队尾int q[N], hh = 0, tt = -1;// 向队尾插入一个数q[ ++ tt] = x;// 从队头弹出一个数hh ++ ;// 队头的值q[hh];// 判断队列是否为空if (hh <= tt){}2.循环队列// hh 表示队头,tt表示队尾的后一个位置int q[N], hh = 0, tt = 0;// 向队尾插入一个数q[tt ++ ] = x;if (tt == N) tt原创 2020-05-09 08:45:51 · 302 阅读 · 0 评论 -
~~栈(数据结构)
模板// tt表示栈顶int stk[N], tt = 0;// 向栈顶插入一个数stk[ ++ tt] = x;// 从栈顶弹出一个数tt -- ;// 栈顶的值stk[tt];// 判断栈是否为空if (tt > 0){}原创 2020-05-09 08:44:32 · 175 阅读 · 0 评论 -
~~双链表(数据结构)
模板// e[]表示节点的值,l[]表示节点的左指针,r[]表示节点的右指针,idx表示当前用到了哪个节点int e[N], l[N], r[N], idx;// 初始化void init(){ //0是左端点,1是右端点 r[0] = 1, l[1] = 0; idx = 2;}// 在节点a的右边插入一个数xvoid insert(int a, in...原创 2020-04-30 22:15:06 · 250 阅读 · 0 评论 -
~~单链表(数据结构)
模板// head存储链表头,e[]存储节点的值,ne[]存储节点的next指针,idx表示当前用到了哪个节点int head, e[N], ne[N], idx;// 初始化void init(){ head = -1; idx = 0;}// 在链表头插入一个数avoid insert(int a){ e[idx] = a, ne[idx] = h...原创 2020-04-30 22:14:23 · 193 阅读 · 0 评论 -
~~匈牙利算法
时间复杂度是 O(nm), n 表示点数,m 表示边数int n1, n2; // n1表示第一个集合中的点数,n2表示第二个集合中的点数int h[N], e[M], ne[M], idx; // 邻接表存储所有边,匈牙利算法中只会用到从第一个集合指向第二个集合的边,所以这里只用存一个方向的边int match[N]; // 存储第二个集合中的每个点当前匹配的第...原创 2020-04-30 22:11:53 · 351 阅读 · 0 评论 -
~~染色法判别二分图
时间复杂度是 O(n+m), n 表示点数,m 表示边数int n; // n表示点数int h[N], e[M], ne[M], idx; // 邻接表存储图int color[N]; // 表示每个点的颜色,-1表示未染色,0表示白色,1表示黑色// 参数:u表示当前节点,c表示当前点的颜色bool dfs(int u, int c){ co...原创 2020-04-30 22:11:10 · 287 阅读 · 0 评论 -
~~Kruskal算法
时间复杂度是 O(mlogm), n 表示点数,m 表示边数int n, m; // n是点数,m是边数int p[N]; // 并查集的父节点数组struct Edge // 存储边{ int a, b, w; bool operator< (const Edge &W)const { return...原创 2020-04-30 22:10:26 · 183 阅读 · 0 评论 -
~~朴素版prim算法
时间复杂度是O(n2+m), n 表示点数,m 表示边数int n; // n表示点数int g[N][N]; // 邻接矩阵,存储所有边int dist[N]; // 存储其他点到当前最小生成树的距离bool st[N]; // 存储每个点是否已经在生成树中// 如果图不连通,则返回INF(值是0x3f3f3f3f), 否则返回最小生成...原创 2020-04-30 22:09:13 · 304 阅读 · 0 评论 -
~~floyd算法
时间复杂度是 (n3), n 表示点数初始化: for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= n; j ++ ) if (i == j) d[i][j] = 0; else d[i][j] = INF;// 算法结束后,d[a][b]表示a到b的最短距...原创 2020-04-30 22:08:00 · 180 阅读 · 0 评论 -
~~spfa判断图中是否存在负环
时间复杂度是 O(nm), n 表示点数,m 表示边数int n; // 总点数int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边int dist[N], cnt[N]; // dist[x]存储1号点到x的最短距离,cnt[x]存储1到x的最短路中经过的点数bool st[N]; // 存储每个点是否在队...原创 2020-04-30 22:07:05 · 336 阅读 · 0 评论 -
~~spfa 算法(队列优化的Bellman-Ford算法)(附模板题)
模板时间复杂度 平均情况下 O(m),最坏情况下 O(nm), n表示点数,m 表示边数int n; // 总点数int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边int dist[N]; // 存储每个点到1号点的最短距离bool st[N]; // 存储每个点是否在队列中// 求1号点到n号点的最...原创 2020-04-14 15:58:18 · 456 阅读 · 0 评论 -
~~Bellman-Ford算法
时间复杂度 O(nm), n 表示点数,m 表示边数int n, m; // n表示点数,m表示边数int dist[N]; // dist[x]存储1到x的最短路距离struct Edge // 边,a表示出点,b表示入点,w表示边的权重{ int a, b, w;}edges[M];// 求1到n的最短路距离,如果无法从1走到n,则返回...原创 2020-04-13 22:08:13 · 200 阅读 · 0 评论 -
~~堆优化版dijkstra
时间复杂度 O(mlogn), n 表示点数,m 表示边数typedef pair<int, int> PII;int n; // 点的数量int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边int dist[N]; // 存储所有点到1号点的距离bool st[N]; // 存储每个点的最短...原创 2020-04-13 22:06:08 · 250 阅读 · 0 评论 -
~~朴素dijkstra算法
时间复杂是 O(n2+m), n 表示点数,m 表示边数int g[N][N]; // 存储每条边int dist[N]; // 存储1号点到每个点的最短距离bool st[N]; // 存储每个点的最短路是否已经确定// 求1号点到n号点的最短路,如果不存在则返回-1int dijkstra(){ memset(dist, 0x3f, sizeof dist); ...原创 2020-04-13 22:05:14 · 338 阅读 · 0 评论 -
~~拓扑排序
时间复杂度 O(n+m), n 表示点数,m 表示边数bool topsort(){ int hh = 0, tt = -1; // d[i] 存储点i的入度 for (int i = 1; i <= n; i ++ ) if (!d[i]) q[ ++ tt] = i; while (hh <= tt)...原创 2020-04-13 22:03:51 · 155 阅读 · 0 评论 -
~~树与图的遍历
时间复杂度 O(n+m), n 表示点数,m 表示边数(1) 深度优先遍历int dfs(int u){ st[u] = true; // st[u] 表示点u已经被遍历过 for (int i = h[u]; i != -1; i = ne[i]) { int j = e[i]; if (!st[j]) dfs(j); }...原创 2020-04-13 22:02:41 · 197 阅读 · 0 评论 -
~~树与图的存储
树是一种特殊的图,与图的存储方式相同。对于无向图中的边ab,存储两条有向边a->b, b->a。因此我们可以只考虑有向图的存储。(1) 邻接矩阵:g[a][b] 存储边a->b(2) 邻接表:// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点int h[N], e[N], ne[N], idx;// 添加一条边a->b...原创 2020-04-13 22:01:01 · 207 阅读 · 0 评论 -
~~分解质因数法求组合数
当我们需要求出组合数的真实值,而非对某个数的余数时,分解质因数的方式比较好用:1. 筛法求出范围内的所有质数2. 通过 C(a, b) = a! / b! / (a - b)! 这个公式求出每个质因子的次数。 n! 中p的次数是 n / p + n / p^2 + n / p^3 + …3. 用高精度乘法将所有质因子相乘int primes[N], cnt; // 存储所有质数...原创 2020-04-13 21:59:08 · 1260 阅读 · 0 评论