![](https://img-blog.csdnimg.cn/20201014180756930.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
codeforces
Mr.Twh
这个作者很懒,什么都没留下…
展开
-
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 · 76 阅读 · 0 评论 -
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 >原创 2021-03-07 22:36:41 · 167 阅读 · 0 评论 -
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 · 97 阅读 · 0 评论 -
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 · 80 阅读 · 0 评论 -
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 · 77 阅读 · 0 评论 -
cf - 1494A ABC String
1494A ABC String// 思路要想是一个合法的括号序列,必然左括号的数量 == 右括号的数量。而左右括号可以由A,B,C三个字符代替。这说明必然max(A,B,C) = 剩余两个数量之和。而第一个字符必然只能由代替括号。由以上就可以将字符序列替换成括号序列。再判断括号序列是否合法即可。// 判断括号序列的合法性:遇到左括号进栈,右括号出栈。注意右括号出栈是栈必须不为空,如果为空即不合法的序列。最后若栈中还有元素也是不合法序列。#include<iostream&g原创 2021-03-06 13:55:43 · 88 阅读 · 0 评论 -
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 · 164 阅读 · 0 评论 -
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 阅读 · 0 评论 -
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 · 186 阅读 · 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 · 147 阅读 · 2 评论 -
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 · 67 阅读 · 1 评论 -
cf - 1462D - Add to Neighbour and Remove
1462D - Add to Neighbour and Remove在这里插入代码片原创 2021-03-03 22:18:53 · 104 阅读 · 0 评论 -
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 · 79 阅读 · 0 评论 -
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 · 142 阅读 · 1 评论 -
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 · 122 阅读 · 0 评论 -
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 · 107 阅读 · 0 评论 -
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 阅读 · 0 评论 -
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 · 221 阅读 · 0 评论 -
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 · 163 阅读 · 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 · 213 阅读 · 0 评论 -
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 · 139 阅读 · 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 · 370 阅读 · 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 · 113 阅读 · 0 评论 -
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 · 123 阅读 · 0 评论