自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(33)
  • 收藏
  • 关注

原创 最小生成树

最小生成树1.prim()算法2.kruskal()算法1.prim()算法2.kruskal()算法kruskal();[一直在维护一个生成森林(一棵树也可以看作一个生成森林),不断压缩森林的过程]即一开始有n个连通块,将其压缩至一个(可以是多个)的过程:(1) 边权值从小到大排序(2) 依次枚举每条边,如果该边的两个端点已经连通,则pass 否则连通这两个点,并累加答案作用:用最少边使得所有点连通的,且边权之和最小模板存在必选边的最小生成树1存在必选边的最小生成树2

2021-04-04 22:29:01 97

原创 二叉树

二叉树1.用数组建立二叉树2.完全二叉树(满二叉树)3.二叉搜索树1.用数组建立二叉树const int N = 40;int v[N],l[N],r[N]; // 分别表示根节点为i的 值,左孩子,右孩子。2.完全二叉树(满二叉树)如果按层次遍历的顺序给二叉树节点依次标号(1,2...n),完全二叉树满足:根节点标号为i,则左孩子标号为2 * i,右孩子标号为 2 * i + 1.所以据此可以用数组建树注意普通二叉树也可以用这个规律,但会产生大量的空节点,会浪费大量内存。一个节点数为n的

2021-04-01 14:20:00 81

原创 链表

链表1.翻转链表1题解2.翻转链表2题解

2021-03-19 14:25:48 86

原创 cf - 1426D - Non-zero Segments

1426D - Non-zero Segments// 思路不难发现题目要求破坏所有连续子段和为0的区间。对于这种枚举连续子段和等于某一个特定的数,可以采用前缀和的思想。如果a[l,r]这一段和为0,那么s[l - 1] = s[r].[s数组为a的前缀和数组]所以求出前缀和之后据此就可快速找到连续子段和为0的区间。几个细节:1.如果s[x] = 0,它自身需要被计数。因为这代表着a[1..x]这段区间2.破坏区间:如果找到s[x1] = s[x2].破坏它就需要在这x2之前插入一个巨大的

2021-03-14 00:08:34 77

原创 排列组合问题

排列组合问题1.圆排列1.圆排列圆排列:指从n个不同元素中取出m(1≤m≤n)个不同的元素排列成一个环形,既无头也无尾。两个圆排列相同当且仅当所取元素的个数相同并且元素取法一致,在环上的排列顺序一致。计算公式:n个元素的圆排列总数为: (n - 1)!.详解题目#include<iostream>using namespace std;typedef long long ll;int main(){ int n; cin >> n;

2021-03-12 22:49:30 815

原创 cf - 1444A - Division

1444A - Division// 求 一个最大的x,x 满足 是 p 的约数,不是q的倍数1. p < q || p % q != 0,显然 p 就是答案2. 对于p % q == 0的情况,朴素想法是求出p的所有约数然后寻找最大的不能被q整除的数。然后p的范围太大。所以转而分解q。3.q = a1 ^ x1 * a2 ^ x2 * ... ^ an * xn.因为p是q的倍数。所以p = x * a1 ^ y1 * a2 ^ y2 * ... * an ^ yn其中(y1 &gt

2021-03-07 22:36:41 170

原创 cf - 1443C - The Delivery Dilemma

1443C - The Delivery Dilemma// 排序加贪心1.如果全用a数组送,a数组中的最大的数决定时间2.同样全用b数组送,b数组之和决定时间。#include<iostream>#include<algorithm>using namespace std;const int N = 2e5 + 10;typedef pair<int,int> PII;typedef long long ll;PII s[N];ll sum[N]

2021-03-07 22:26:03 98

原创 cf - 1452D - Radio Towers

1452D - Radio Towers// 找规律分子是斐波拉契数列,分母是2 ^ n.#include<iostream>using namespace std;const int mod = 998244353,N = 200010;typedef long long ll;ll a[N];ll qmi(ll a,ll b){ ll res = 1; while(b) { if(b & 1) res = res *

2021-03-07 22:22:14 83

原创 cf - 1451C - String Equality

1451C - String Equality// 思路第一个操作的作用: 交换相邻的两个元素即意味着可以任意的重排原序列第二个操作的作用: 相邻且相同的k个字符可以转换成下一个字符但是z 不能转换成 a。这意味着b数组中的a只能由a数组中原生的a进行匹配。所以很自然的思路就是先把a匹配完,然后如果还有剩余的就转换为b。不能转换即得不到b数组,因为这多余的a怎么也无法与b数组中的元素匹配了。依次处理b,c,...,z即可。#include<iostream>#include&l

2021-03-06 14:42:45 80

原创 cf - 1494A ABC String

1494A ABC String// 思路要想是一个合法的括号序列,必然左括号的数量 == 右括号的数量。而左右括号可以由A,B,C三个字符代替。这说明必然max(A,B,C) = 剩余两个数量之和。而第一个字符必然只能由代替括号。由以上就可以将字符序列替换成括号序列。再判断括号序列是否合法即可。// 判断括号序列的合法性:遇到左括号进栈,右括号出栈。注意右括号出栈是栈必须不为空,如果为空即不合法的序列。最后若栈中还有元素也是不合法序列。#include<iostream&g

2021-03-06 13:55:43 89

原创 cf - 1494B - Berland Crossword

1494B - Berland Crossword// 思路显然,四个角上的数可以影响两个方向的黑色块。所以只需要枚举四个角上是否存在黑块,再判断剩下的数是否满足要求即可。#include<iostream>using namespace std;int n;bool check(int x){ if(x >= 0 && x <= n - 2) return true; return false;}int main(){

2021-03-05 22:58:35 165

原创 cf - 1453B - Suffix Operations

1453B - Suffix Operations// 思路因为只能操作后缀数组,所以必然是让长度为1的后缀数组相等,然后是长度为2的,然后是3...n的。如果不考虑修改数,那么总操作数就是所有相邻两个数的差值绝对值之和那么修改数必然就是改变该数为它左右两个数之间的一个,枚举每个数找到那个使得差值改变最多的数即可。#include<iostream>#include<cmath>using namespace std;const int N = 2e5 + 10

2021-03-05 22:51:57 68

原创 cf - 1459B - Move and Turn

1459B - Move and Turn// 思路1.如果n是偶数,说明y方向要走 n / 2 步, x 方向要走 n / 2 步。y方向 走 n / 2步,有n /2 + 1种可能的坐标:向上走 n / 2步,向下走 0 步向上走 n / 2 - 1步,向下走 1 步...向下走 0 步,向上走 n / 2 步。x方向同理总的不同坐标数就是: (n / 2 + 1) * (n / 2 + 1) 种2.如果n是奇数,说明x方向要走 n / 2 步,y方向要走 n / 2 + 1步

2021-03-04 22:29:34 188 1

原创 cf - 1454D - Number into Sequence

1454D - Number into Sequence// 思路如果不考虑a数组元素之间的整除关系,a数组就是n根据唯一分解定理分解后的结果。所以 假设 n = a1^p1 * a2 ^ p2 * ... * an ^ pn只要找到max(p1,p2...pn),假设为p,对应的底数为a。可以构建的数组就是:(p - 1) 个 a,最后一个数就是 a * (其他的所有数)。#include<iostream>#include<cstring>using name

2021-03-04 22:18:02 148 2

原创 搜索 - 多源bfs

多源bfs// 思路建立虚拟源点,将所有起点加入队列中1.题目1#include<iostream>#include<cstring>#include<queue>using namespace std;const int N = 1010;typedef pair<int,int> PII;int dis[N][N];char g[N][N];queue<PII> q;int n,m;void bfs()

2021-03-04 21:17:02 113 1

原创 cf - 1461B - Find the Spruce

1461B - Find the Spruce// 关键思想 对于顶点(i,j)能构成树的数量 == min(顶点(i + 1,j - 1)构成树的数量,顶点(i + 1,j)构成树的数量,顶点(i + 1,j + 1)构成树的数量) + 1#include<iostream>#include<cstring>using namespace std;const int N = 510;int d[N][N];int main(){ int t;

2021-03-03 22:24:48 104 1

原创 cf - 1461C - Random Events

1461C - Random Events// 数学推出公式即可#include<iostream>#include<cstdio>using namespace std;const int N = 100010;int a[N],b[N];double p[N];int n,m;int main(){ int t; cin >> t; while(t --) { cin >> n

2021-03-03 22:20:52 69 1

原创 cf - 1462D - Add to Neighbour and Remove

1462D - Add to Neighbour and Remove在这里插入代码片

2021-03-03 22:18:53 104

原创 cf - 1486B - Eastern Exhibition

1486B - Eastern Exhibition// 中位数对于一个长度为n的有序(从小到大)序列x(n):如果n为偶数,中位数为 (x[n / 2 + 1] - x[n / 2]) / 2,如果n为奇数,中位数为 x[n / 2 + 1].// 性质中位数x到数组中其余数的距离之和最小,如果n为偶数 [x[n / 2],x[n / 2] + 1] 之间所有数到数组中其余数距离之和都最小// 二维转化为一维的情况:1. 先只看x方向2. 再看y方向#include<ios

2021-03-01 22:47:31 84

原创 cf 1492C - Maximum width

1492C - Maximum width// 直观想法对于t中的每一个字符找到它在s中的最左的位置和最右边的位置,分别设为l[i]和r[i]。最终答案就是max(r[i + 1] - l[i])注意的是每一个l[i] 要大于 r[i - 1],每一个r[i] 要小于 l[i + 1]。#include<iostream>using namespace std;const int N = 2e5 + 10;char s[N],t[N];int r[N],l[N]; //

2021-03-01 21:37:23 143 1

原创 字符串

字符串1. 字符串哈希1. 字符串哈希题目链接:字符串哈希// 哈希方式1.将字符串看成p进制数后得出的值对M取模。如(ABC) = 1 * p^2 + 2 * p^1 + 3 * p^0;2.预处理出字符串每一个前缀(包括自身)的哈希值h[i]3.任意子串的哈希值的计算。如[l,r]这个子串的哈希值:[l,r]对应的位数是p ^ (r - l) ... p ^ 0 ,以h[r]为基准所以h[l,r] = x[l] * p ^(r - l) + x[l + 1] * p ^(r - l -

2021-02-20 14:10:52 81

原创 cf - 1461D - Divide and Summarize

1461D - Divide and Summarize//模拟根据题意一个长度为n的数组最多能划分多少次?logn次。将每次划分的和全部存下来就可以O(1)的查询.注意划分时候的边界和细节。#include<iostream>#include<set>#include<algorithm>using namespace std;typedef long long ll;const int N = 200010;int a[N];ll sum[N

2021-02-20 10:49:40 123

原创 cf - 1462E1 - Close Tuples (easy version)

@[TOC](1462E1 - Close Tuples (easy version))// 思路先从小到大排序设要找的三元组最小的数为x.从x后开始查找直至找到最后一个数m -> m - x <= 2.那么在区间[x + 1,m]任选两个数都满足要求#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int N = 200010;

2021-02-19 11:40:42 110

原创 cf - 1466C - Canine poetry

1466C - Canine poetry// 关键思想:任何一个回文串必定包含一个要么是长度为2要么长度为3的回文串只需要破坏长度为2和3的回文串即可。#include<iostream>#include<string>using namespace std;const int N = 200010;bool vis[N];int main(){ int t; cin >> t; while(t --) {

2021-02-19 10:11:29 117

原创 cf - 1490E - Accidental Victory

1490E - Accidental Victory// 思路毫无疑问如果数字为x能赢,那么>=x的都能取胜,反之如果x不能赢,小于x的都不能取胜。典型的二分只需找到这个临界的x就行。那么让x能赢最优操作无疑是先让x和比他小的比,吃小的分,在和后面比。以此设计check()函数即可#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int

2021-02-19 09:52:16 225

原创 cf - 1490F - Equalize the Array

1490F - Equalize the Array// 思路题目最终要求数组中每个元素出现的次数一样多,不妨设为c次有:【假设每个元素出现的次数为cnt】对于出现次数少于c次:没有办法只能全部删除。对于出现次数多于c次:只需删除cnt - c次即可。#include<iostream>#include<map>#include<set>#include<algorithm>using namespace std;const int

2021-02-19 09:44:15 164 1

原创 cf-1468K - The Robot

1468K - The Robot// 思路关键思想:障碍物的坐标一定是机器人行进路线上的一个坐标枚举机器人走过的所有坐标即可时间复杂度(O(n^2)) n <= 5000;#include<iostream>#include<string>using namespace std;int main(){ int t; cin >> t; while(t --) { string s;

2021-02-18 14:06:44 218

原创 cf -1469C - Building a Fence

1469C - Building a Fence// 思路对于第i块栅栏,它所处的高度范围由第i - 1块栅栏和地面高度决定。1. 用l[i]表示第i块栅栏的最低高度,r[i]表示第i块栅栏的最高高度。2. l[i]: 因为两块栅栏之间必须要接触1米,所以根据这个条件 相对于第i - 1块栅栏的最低高度l[i - 1],l[i]还可以下降k - 1米。 所以l[i] = l[i - 1] - k + 1; 又因为最低高度要大于地面的高度。 所以l[i] = max(l[

2021-02-18 14:02:11 143 1

原创 cf 1487C - Minimum Ties

1487C - Minimum Ties// 思维1. n支队伍一共要比赛n * (n - 1) / 2次。2. 如果没有平局,那么n支队伍的总得分为 3 * n * (n - 1) / 2(#); 因为一局比赛胜者加3分,败者加0分,所以两支队伍总得分加33. 每支队伍得分相同为x -> x = 3 * n * (n - 1) / 2 / n = 3 * (n - 1) / 2;4. 发现只有n为奇数时,x 才为整数。也就是说n为奇数时,不需要平局 当n为偶数时,x不为整数,想

2021-02-17 11:36:34 377 4

原创 cf 1475C - Ball in Berland

1475C - Ball in Berland// 思维题每一对配对关系可以看作两个人之间连接了一条边。设a[i] 为 编号为i的男孩所有边的数量, b[i] 为 编号为i的女孩所有边的数量。枚举每一对配对关系,假设选择当前第x对配对关系,男孩编号为i,女孩编号为j.第二对 组合可以选择的方案有:k - a[i] - b[j] + 1;因为选择了第i个男孩和第j个女孩,所以第二对组合中不能再出现这两个人,因此与他们相关的边全部作废。(a,b) 这条边被作废两次,所以要加1.最终答案要

2021-02-16 22:56:02 114

原创 cf 1476C - Longest Simple Cycle

1476C - Longest Simple Cycle// 线性dp关键思想:对于每一个环,它必然包含一个完整的链且属于环的最右边。#include<iostream>#include<cstring>#include<cmath>using namespace std;typedef long long ll;const int N = 100010;ll s[N],a[N],b[N];ll f[N]; // 表示以第i条链为环的最右部分的

2021-02-16 21:23:06 124

原创 dp问题——背包问题及一些应用

01背包及一些应用1.基础01背包2.应用(1)正整数分组扩展1.基础01背包// 状态表示f[i][j]表示从前i个物品中选且总体积不超过j的所有方案。// 转移针对第i个物品做出选择。1.不选第i个物品。 相当于从前i - 1个物品中选且总体积不超过j的所有方案表示为f[i - 1][j].2.选择第i个物品。剔除第i个物品后,相当于从前i - 1个物品中选且总体积不超过j - v[i]的所有方案.表示为f[i - 1][j - v] + w。【w,v分别为第i个物品的价值和体积】注

2021-02-09 22:54:07 210 1

原创 dp问题——最大子段和及其扩展

dp问题——最大子段和1. 基础(1)最大子段和解法2. 扩展1. 基础(1)最大子段和题目连接:最大子段和解法//状态表示及转移用f[i] 表示 以a[i]结尾的连续子序列的集合。根据最后一个元素的不同,可将集合如此划分:1. 子序列长度为1 ————> f[i] = a[i].2. 子序列长度大于1 ————> f[i] = f[i - 1] + a[i].(因为f[i] 表示以a[i]结尾的连续子序列,当长度大于1时 a[i - 1]必定存在。)根据题目要求,求

2021-02-03 22:55:04 409 1

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除