合集-思维题

摘要:原题链接 小记 在一位高人的帮助下通过这题 主要是二分+双指针(聚焦型双指针?) 时间复杂度为\(O(t*n*logn)\) 题解 二分这个k对应的值,对于每个二分出来的值,找出共有几个和小于它,核心如下: 如果恰好有\(a[l_1]+a[r_1]<x\) , 那么\(a[l_1]-a[i]<x,( 阅读全文
posted @ 2024-01-16 18:33 纯粹的 阅读(72) 评论(0) 推荐(0)
摘要:原题链接 题解 本题中,每一位数字的每一次变化都会对答案贡献1,所以对于第 \(i\) 位数字而言,它的贡献为从最左边到现在的数,设为 \(f[i]\) 所以答案为 \(\sum_{i=1}^{n}f[i]\),可以用高精度加法解决 然而这样一来时间复杂度就超了 \(O(t·n^2)\) 所以我们尝 阅读全文
posted @ 2024-02-18 22:53 纯粹的 阅读(90) 评论(0) 推荐(0)
摘要:原题链接 题解 如果 \((a_i+a_j)\ mod\ x==0\) 那么 \((a_i\ mod\ x+a_j\ mod\ x)\ mod\ x==0\) 如果 \((a_i-a_j)\ mod\ y==0\) 那么 \(a_i\ mod\ y==a_j\ mod\ y\) 所以我们可以把每个 阅读全文
posted @ 2024-02-19 18:44 纯粹的 阅读(78) 评论(0) 推荐(0)
摘要:原题链接 题解 我们令 a出现在b前面 \(\to\) 建立一条a到b的有向边 如果有强连通分量,那么no 每张截图除了第一个人,其余人均按相对位置排序 这道题就变成了给定若干个相对位置,求是否存在可能的绝对位置 我们可以建图,作拓扑排序,一个节点能被遍历到当且仅当其所有的父节点都被遍历到 当且仅当 阅读全文
posted @ 2024-02-19 21:12 纯粹的 阅读(50) 评论(0) 推荐(0)
摘要:原题链接 题解,请看这里 细节 有除法的求模要求逆元 code #include<bits/stdc++.h> #define mod 998244353 #define ll long long using namespace std; inline void read(ll &x) { x = 阅读全文
posted @ 2024-02-20 05:21 纯粹的 阅读(47) 评论(0) 推荐(0)
摘要:原题链接 题解 一只青蛙 \(x\) 天来回跳 $\to $ 一只青蛙从左往右跳 \(2x\) 次 \(\to\) \(2x\) 只青蛙从左往右跳一次 规律:对于任意长度为 \(y\) 的区间,其区间和一定不小于 \(2x\) 证明过程请看题解区,非常优雅 upd: 如果想从起点跳到石头上,那么前y 阅读全文
posted @ 2024-02-21 01:44 纯粹的 阅读(132) 评论(0) 推荐(0)
摘要:原题链接 题解 由于执行收获操作后所有数组清零,清零后的数组最快捷的加分方法是加一收获一,所以就是第一次加多少次 然后第一次加完最多收获 \(n\) 分,相当于清零后执行总共 \(2n\) 次 所以只需要判断第一次加 &[0,2n-1]& 次加后收获时能收获多少就行了 code,注意细节 #incl 阅读全文
posted @ 2024-02-23 16:05 纯粹的 阅读(40) 评论(0) 推荐(0)
摘要:原题链接 题解 对于原序列而言,如果第一个元素是最大值或最小值,那么l肯定不能落在这,由于r也不可能落在这,所以相当于这个元素被剔除了 那么对于区间 \([1,n]\) 的研究就等价于对 \([2,n]\) 的研究 由此可以推出之后的做法 code #include<bits/stdc++.h> u 阅读全文
posted @ 2024-02-24 01:46 纯粹的 阅读(39) 评论(0) 推荐(0)
摘要:原题链接 题解 一个节点的答案一定是最大父节点+1 code #include<bits/stdc++.h> using namespace std; int ans[100005]={0}; int in[100005]={0}; vector<int> G[100005]; struct uni 阅读全文
posted @ 2024-02-24 13:09 纯粹的 阅读(27) 评论(0) 推荐(0)
摘要:原题链接 题解 设前半部分对两个集合贡献的差为a,后半部分贡献为b 若 \(a==b\) 则 差为a的组合数(被选上,和在哪个集合无关)sa 与b的组合数的sb 此时对答案的贡献为 \(sa·sb\) 所以穷举所有差的组合,然后累加 设差为集合A-集合B 每个元素对差的贡献有三种可能,要么加要么减要 阅读全文
posted @ 2024-02-26 03:31 纯粹的 阅读(89) 评论(0) 推荐(0)
摘要:原题链接 题解 折半搜索 前半部分的所有组合(二进制表示)存起来,然后遍历后半部分的组合,找到第一个加起来不大于M的 = code #define ll long long #include<bits/stdc++.h> using namespace std; inline void read(l 阅读全文
posted @ 2024-02-26 13:54 纯粹的 阅读(38) 评论(0) 推荐(0)
摘要:原题链接 题解 要让水平块尽可能多,垂直块尽可能少 垂直块最少为零,也就是说,一行里全部都是水平块,可不可能?答案是可能的,一定存在某种组合使得水平块刚好塞满一行 那么这种方块数最多的组合是多少?每个方块长度都为2,如果 \(m\) 为奇数,最后一个方块长度为 3 题解 #include<bits/ 阅读全文
posted @ 2024-02-28 14:17 纯粹的 阅读(30) 评论(0) 推荐(0)
摘要:原题链接 题解 逆序对数最小的排列是严格升序的排列,因此我猜想有一个严格升序的排列最优的 证明; 冒泡排序,我们把排列a中最大的元素不断地往右作相邻对换,这样一来,序列a的逆序对数必定减少一,序列b的逆序对数可能减少一,可能不变,可能加一,但是两个排列的总逆序对数不可能增加。 然后再逆着想验证了这种 阅读全文
posted @ 2024-02-28 16:03 纯粹的 阅读(34) 评论(0) 推荐(0)
摘要:原题链接 题解 既然是按位异或,那么我们尝试在二进制视角下考虑问题 我们发现,当两个数的同一位置上都有1的时候,这个1消与不消对结果没有影响,而这个位置上其中一个有一,另一个没有一时,我们可以通过x来转移一 所以在ab俩个数出现第一个10情况不同的位置之后,我们要尽可能地把剩余的一尽可能地移到较小的 阅读全文
posted @ 2024-02-28 16:12 纯粹的 阅读(69) 评论(0) 推荐(0)
摘要:原题链接 题意简述 把1移到移到左边最近的0的位置,请问形成一片连续的一需要移多少次? 题解 像坦克的履带,对于两群不相连的1,右边想和左边相连至少要走中间的0的数量的步数,这下就可以遇到零才执行收获操作了 code #include<bits/stdc++.h> using namespace s 阅读全文
posted @ 2024-02-28 16:17 纯粹的 阅读(73) 评论(0) 推荐(0)
摘要:原题链接 题解 什么时候会输? 首先我们要贪心一次性把离自己最近的怪物消灭掉,但是一回合内消灭掉了一个怪物之后还有剩余,我么就把剩余的扣在第二个离自己最近的怪物上 如果我当前回合没有消灭怪物,并且怪物下一回合就到零点,那我就输了 我们可以想象成这样的动画:我们每回合一次性往怪物身上丢出所有的手雷,手 阅读全文
posted @ 2024-02-28 16:54 纯粹的 阅读(50) 评论(0) 推荐(0)
摘要:原题链接 题解 给定数组c,和若干查询区间,请问能否改变区间中的每一个值且区间和还不变? 对于任意一个数,不是加就是减,而对于整个数组而言,加了多少就要减多少 而对于等于1的元素而言,只能加,因此我们令元素为1的为待加元素,其他元素均为待减元素 找出所有大于1的元素把他们变成一,然后差值累加到一个变 阅读全文
posted @ 2024-02-28 17:12 纯粹的 阅读(61) 评论(0) 推荐(0)
摘要:原题链接 题解 对于任何一个粘液块s而言,要么是从左边被吞并,要么是从右边被吞并,根据对称性,两边的决策是一样的,因此先考虑右边 对于被右边吞并而言,有以下几个特征 1.起始粘液一定是吞掉了s右边一整块连续的粘液 2.右边区间一定存在大小不同的相邻粘液,这样才能发动吞并 3.由一二猜想,只要存在不同 阅读全文
posted @ 2024-02-28 17:48 纯粹的 阅读(89) 评论(0) 推荐(0)
摘要:原题链接 题解 暴力可不可以关键看时间复杂度 x从1遍历到 log2(1e6) ,y同理 时间复杂度约为 \(O(20·20)\) 草 code #include<bits/stdc++.h> #define ll long long using namespace std; int main() 阅读全文
posted @ 2024-02-28 18:01 纯粹的 阅读(58) 评论(0) 推荐(0)
摘要:原题链接 题解 将序列排序后,设最小值为k,那么 \(2~n\) 的每个元素都可以表示为 \(nk+b,b\in[0,k-1]\) 如果 \(2~n\) 的元素中存在 \(k\) 且 \(b\) 均为零,一定失败 code #include<bits/stdc++.h> using namespac 阅读全文
posted @ 2024-02-28 18:49 纯粹的 阅读(63) 评论(0) 推荐(0)
摘要:原题链接 题解 对于一个数,我们将其转换成二进制,然后补零到31位 我们发现,能和数x配对的数只有一个,那就是 按位翻转后的x,即x和 \(2^{31}-1\) 异或的值 所以我们要找有没有能互相配对的值,以及组数,配对用map? code #include<bits/stdc++.h> using 阅读全文
posted @ 2024-02-28 19:13 纯粹的 阅读(45) 评论(0) 推荐(0)
摘要:原题链接 题解 如果一开始就把所有数乘起来,结果会太大,所以我们把逆着来,先找到最后一个元素,然后乘法求模 code #include<bits/stdc++.h> using namespace std; long long a[200005]={0},ans[200005]={0}; int m 阅读全文
posted @ 2024-02-28 19:20 纯粹的 阅读(29) 评论(0) 推荐(0)
摘要:原题链接 题解 巧妙的背包问题 我可以用按顺序遍历城堡,顺便表示出遍历到当前城堡时用掉了多少兵力,这样是可以穷尽所有兵力派送情况的 同时把这个城堡里的敌方兵力升序排序,然后遍历,表示为了消灭所有兵力小于等于ta的敌人所加的分 code #include<bits/stdc++.h> using na 阅读全文
posted @ 2024-03-03 20:28 纯粹的 阅读(48) 评论(0) 推荐(0)
摘要:原题链接 题解 设 \(sum\) 为总能力 则若 \(sum\) 是 \(F\) 的倍数 \(\to\) \(sum\ mod\ F=0\) 根据加法求模的特性,我们可以设 \(dp[i][j]\) 为 加上第 \(i\) 个元素后, 模为 \(j\) 的方案数 转移方程移得 注意一个细节:按照遍 阅读全文
posted @ 2024-03-03 22:55 纯粹的 阅读(72) 评论(0) 推荐(0)
摘要:原题链接 题解 太妙了 如果能出去,那么出去的时间一定为让我出去的那个垃圾掉落的时间,且在此之前我所在的高度能撑到我垃圾掉落 如果出不去,我肯定一直呆在井底不动 所以我们可以以高度为变量 设每个高度能撑到的最久的时间 而每个垃圾在拿到的一瞬间要么吃要么搭,所以我们穷举,两个都要,如果搭,那么搭上去的 阅读全文
posted @ 2024-03-03 23:38 纯粹的 阅读(28) 评论(0) 推荐(0)
摘要:原题链接 题解 遍历主件,和还剩下多少钱的情况下,最多有五种购买决策 1.不买 2.买主件 3.买主件+附件1 4.买主件+附件2 5.买主件+附件1+附件2 如果当前的钱够买,那就买买看,然后加上剩下的钱能买的最大值 code #include<bits/stdc++.h> using names 阅读全文
posted @ 2024-03-04 17:49 纯粹的 阅读(40) 评论(0) 推荐(0)
摘要:原题链接 题解 核心技巧:两次搜索 第一次搜索: 搜索出 \(f[now][i]\) 以 \(now\) 为根节点的子树且距离根节点恰好为 \(i\) 的节点的个数 搜索完了之后,把范围 \(k\) 以内的累加 第二次搜索: 由于整棵树的根节点的 \(f\) 等于整棵树里距离不大于 \(k\) 的节 阅读全文
posted @ 2024-03-04 17:56 纯粹的 阅读(66) 评论(0) 推荐(0)
摘要:原题链接 题解 等价于线性代数中求最大无关组的大小 code #include<bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while(t--) { int n; cin>>n; int a[105]={0}; fo 阅读全文
posted @ 2024-03-04 22:42 纯粹的 阅读(46) 评论(0) 推荐(0)
摘要:原题链接 题解 二分加动态维护区间最大值 注意设立变量的含义,改变变量值的规则 code #include<bits/stdc++.h> #define ll long long using namespace std; ll sum[500005]={0}; struct unit { ll x, 阅读全文
posted @ 2024-03-06 19:35 纯粹的 阅读(73) 评论(0) 推荐(0)
摘要:原题链接 题解 思维转换,想象井里的水都来自山上,并把山看成一个点,那么这道题就变成了最小生成树 简证最小生成树原理: 按边权排序,然后遍历,如果这条边的两个点之前每连过,那么就连上,因为这就是这两个点所在集合之间的最短路径了,不然这条边没必要加,因为已经联通了 算是一种贪心? code #incl 阅读全文
posted @ 2024-03-06 23:09 纯粹的 阅读(94) 评论(0) 推荐(0)
摘要:原题链接 题解1: 按边权从大到小排序,如果这条边的两个点没确定关系,那么把他们设为敌人 这样,就成了一棵棵最大生成树(因为有的罪犯之间没有怨气) 由敌人的敌人是朋友可以得出,如果两个点在同一棵树,且距离为偶数,那么代表他们之间互为朋友 code1 #include<bits/stdc++.h> u 阅读全文
posted @ 2024-03-07 18:41 纯粹的 阅读(74) 评论(0) 推荐(0)
摘要:原题链接 题解1:朴素广搜 注意细节 code1 #include<bits/stdc++.h> using namespace std; int poi[4]={-3,1,-1,3}; int main() { string s; cin>>s; queue<string> q; map<stri 阅读全文
posted @ 2024-03-07 20:05 纯粹的 阅读(31) 评论(0) 推荐(0)
摘要:原题链接 题解 抽象化 抽象成点和边,对于抹除一个点,判断整个图是否联通 等价于建立一个点(被抹除点的前一个点),判断这个点与周围点相连后,累积合并次数是否等于点数减一 code #define ll long long #include<bits/stdc++.h> using namespace 阅读全文
posted @ 2024-03-08 14:26 纯粹的 阅读(54) 评论(0) 推荐(0)
摘要:原题链接 题解,终于有一道题一遍过了 强连通分量缩点加本题个性化判断 code #include<bits/stdc++.h> using namespace std; vector<int> G[10005]; int order[10005]={0},low[10005]={0},len=0; 阅读全文
posted @ 2024-03-08 15:04 纯粹的 阅读(41) 评论(0) 推荐(0)
摘要:原题链接 题解 我一开始也很困惑,然后我想要不数据范围小一点我构造看看 当 \(n=5\) 时 \(k=0\) 可不可以 \(k=1\) 可不可以 \(k=2\) 可不可以 然后根据直觉,\(gcd(a,a+1)\) 始终为一,且 一 和任何数的最大公约数都为一,自己和自己的最大公约数还是自己,所以 阅读全文
posted @ 2024-03-08 18:27 纯粹的 阅读(20) 评论(0) 推荐(0)
摘要:原题链接 题解 直观的 \(O(n)\) 算法很容易想到,但是很不幸,挂了 所以我们要想到 \(O(1)\) 的做法 考虑到斐波那契数列非常有规律,所以我们找找规律 奇,奇,偶,奇,奇,偶。。。 code #include<bits/stdc++.h> using namespace std; #d 阅读全文
posted @ 2024-03-08 18:51 纯粹的 阅读(22) 评论(0) 推荐(0)
摘要:原题链接 题解 不能连续选k个元素 \(\to\) 任意每k个元素就有一个不选 \(\to\) 每k个点就有一个断点 \(\to\) 每个点都有可能是断点 \(\to\) dp求解 \(sol.1\) 令 \(f[i]\) 为第i个点为断点且为结尾的最大值 则 \(f[i]=max(f[j]+sum 阅读全文
posted @ 2024-03-09 16:40 纯粹的 阅读(52) 评论(0) 推荐(0)
摘要:原题链接 题解 太巧妙了!! code #include<bits/stdc++.h> using namespace std; int main() { int n,w; cin>>n>>w; int score[605]={0}; for(int i=1;i<=n;i++) { int x; c 阅读全文
posted @ 2024-03-09 19:15 纯粹的 阅读(83) 评论(0) 推荐(0)
摘要:原题链接 思路 求最大区间和 \(\to\) 设每个点为区间右端点时的最大区间和 \(f[i]\) ,则答案一定为 \(max(f[i])\) \(\to\) 求最大的 \(f[i]\) \(\to\) 每个 \(f[i]=max(sum[i]-sum[j-1]),j\in[i-k+1,i]\) \ 阅读全文
posted @ 2024-03-09 21:52 纯粹的 阅读(36) 评论(0) 推荐(0)
摘要:原题链接 题解 太巧妙了 把每个点上方的连续f长度记录下来,然后求每行的柱状图构成的矩形的最大面积 code #include<bits/stdc++.h> using namespace std; int f[1005][1005]={0}; int n,m; struct node { int 阅读全文
posted @ 2024-03-10 14:37 纯粹的 阅读(42) 评论(0) 推荐(0)
摘要:原题链接 题解 1.倒序求 2.求每个点前有多少高度比自己小的 3.高度函数图像是有升有降的,由于要求比自己小的,在求完之后,我们把所有点前比自己小的点缩起来放到自己身上,然后把那些点删掉,再插入自己 这样序列就变成了降序,遍历的时候也只需要遍历那些降序点 code #include<bits/st 阅读全文
posted @ 2024-03-10 15:01 纯粹的 阅读(88) 评论(0) 推荐(0)
摘要:原题链接 题解 原题等价于求以 \(i,(i>=k)\) 为右端点,长度为 \(k\) 的区间内的最大元素 \(\to\) 由于维护的区间是定值,所以我们可以用单调队列维护,单调队列中保证元素大小从头到尾降序,且下标升序 这样一来,我们便可以保证下标在指定范围内,然后取最大值也只需要 \(O(1)\ 阅读全文
posted @ 2024-03-10 15:17 纯粹的 阅读(47) 评论(0) 推荐(0)
摘要:原题链接 题解 把覆盖的区域变成黑色,然后在区域内划几条竖线,一定能分成若干个矩形左右拼接而成的图形 想象一条竖着的线,它的运动轨迹是不连续的,即他会从一个矩形的竖边跳到另一个矩形的竖边,每跳一条竖边都会对借着竖边归属的矩形的信息对这条竖边的激活块进行修改 当竖线的绝对位置发生移动时,计算激活区间产 阅读全文
posted @ 2024-03-10 21:31 纯粹的 阅读(81) 评论(0) 推荐(0)
摘要:原题链接 题解 每个种族的贡献是互不干扰的,因此只需要计算每个族群在每个组数的情况下的解然后累加就行了,由于每个族群在组数大于等于 \(c_i\) 的时候解数不变,所以这里用到了差分小技巧 然后就是计算每个族群在每个组数下的解就行了 code #define ll long long #includ 阅读全文
posted @ 2024-03-12 14:14 纯粹的 阅读(34) 评论(0) 推荐(0)
摘要:原题链接 题解 原题可以理解为 \(\to\) 找出含有最小边权的边双连通分量,然后找出那个边对应的两个节点的第二条路 本题我学会了: 1.代码命名风格要含义清晰,不然很容易搞混,包括变量,自定义函数 2.建边的时候尽量用链表式,因为dalao都在用,看题解方便一点 code #define ll 阅读全文
posted @ 2024-03-12 23:41 纯粹的 阅读(24) 评论(0) 推荐(0)
摘要:原题链接 题解 已知对于一个长度为 \(n\) 的连续+1型上升序列而言,其满足要求的子序列有\(2^n\)个 若我们在该序列下标为 \(k\) 的右边插入一个绝对大于左边,绝对小于右边的数,满足要求的子序列会增加 \(2^k\) 个 由此想到极限构造加二进制,其中最高位的一不用管,其余的每一位生成 阅读全文
posted @ 2024-03-13 23:47 纯粹的 阅读(17) 评论(0) 推荐(0)
摘要:原题链接 题解 易得答案具有单调性,再加上 \(n·m<=1e6\) 故确定了二分 正方形每个数都大于 \(x\) \(\to\) 正方形内每个数减去 \(x\) ,1的数量是否达到 \(x^2\) \(\to\) 差分面积是否达到 \(x^2\) code #include<bits/stdc++ 阅读全文
posted @ 2024-03-14 00:43 纯粹的 阅读(39) 评论(0) 推荐(0)
摘要:原题链接 题解 设 \(len_i\) 为第 \(i\) 次操作后的数组长度, \(last_i\) 为该数组的最后一个数字 那么对于第一个 \(len\) 大于 \(k\) 的 \(i\) 而言 \({A}_{i}[k] \to A_{i-1}[k_1]\) 其中 \(k_1=(k-1)\% le 阅读全文
posted @ 2024-03-14 18:00 纯粹的 阅读(28) 评论(0) 推荐(0)
摘要:原题链接 题解 最大值最小 \(\to\) 二分可行性判断: 二分间断值 \(len\ \to\) 如果原序列 \(a_i-a_{i-1}>len\) \(\to\) 双指针判断有没有 \(b+f\) 使得 \(a_i-len<=b+f<=a_{i-1}+len\) 由于只能使用一次,所以若使用两次 阅读全文
posted @ 2024-03-14 20:36 纯粹的 阅读(45) 评论(0) 推荐(0)
摘要:原题链接 题解 考虑以下决策 \(x+y\in S\) \(\to\) \(y=-x+S_i\) \(y-x\in S\) \(\to\) \(y=x+S_i\) 答案为红线上点的数量加上蓝线上点的数量减去交叉点(整数)的数量 由于 \(S_i<=c\) 所以 交叉点等价于画斜率等于 \(-1\) 阅读全文
posted @ 2024-03-15 15:35 纯粹的 阅读(30) 评论(0) 推荐(0)
摘要:原题链接 题解 太巧妙了!! 原题等效于该分层图,然后广搜 本题中我用了另一种方法建边,因为清空太麻烦了 code #include<bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.t 阅读全文
posted @ 2024-03-15 20:41 纯粹的 阅读(38) 评论(0) 推荐(0)
摘要:原题链接 题解 1.任意两条边在且仅在一条链上 2.一定存在一条链使得其包含边权为0,1的边,这个时候我们要让2不在01所在的链上,即如下情况: 此时01所在链答案为2,02所在链答案为一 3.如果树退化成了链,那么不管怎么构造都一样 由此得出,找出这样 的 T 型节点,即含有三条边的节点,然后在它 阅读全文
posted @ 2024-03-17 19:24 纯粹的 阅读(24) 评论(0) 推荐(0)
摘要:原题链接 题解 \(a\to b,b\to c,a\to c\) 等价于 \(a\to b\to c\) \(a\to z,b\to z\) 也可以等价于 \(a\to b\to z\) 花费不变 所以是并查集,然后累积建边数量 如果 \(finds(a)==finda(z)\) 代表 \(a\) 阅读全文
posted @ 2024-03-17 21:26 纯粹的 阅读(50) 评论(0) 推荐(0)
摘要:原题链接 题解 考虑利用边界和墙来封锁坏人,封锁圈越大,好人的空间就越小。如果一个封锁圈是合理的,那么比他小的封锁圈也一定是合理的,无限小直到包裹坏人的四周 所以贪心地在坏人四周放墙,如果放的过周围有好人在周围,或者有好人但是把终点放了,或者从终点出发无法到达所有的好人(从多元深搜变成了单源广搜) 阅读全文
posted @ 2024-03-18 00:15 纯粹的 阅读(44) 评论(0) 推荐(0)
摘要:原题链接 题解 1.数字最多两位,所以数字的拆解方案惟一 2.数字拆开一定变小,所以最后一个数不拆 3.如果拆开,代表当前数大于前一个数,此时拆开要满足几点要求:后面的个位数不大于前一个数,前面的个位数不大于后一个个位数 code #include<bits/stdc++.h> using name 阅读全文
posted @ 2024-03-18 00:50 纯粹的 阅读(81) 评论(0) 推荐(0)
摘要:原题链接 题解 一看无从下脑,不妨造几个样例观察观察 1 2 3 4 1 2 3 4 此时两边取相同值即可 此时发现无论前半边数字的排列顺序是什么,只要是那几个数字,就不会影响答案 所以交换前半边和后半边的数字会影响答案 1 2 1 4 3 2 3 4 观察样例发现,交换之后,两边会出现一对相同的数 阅读全文
posted @ 2024-03-18 01:00 纯粹的 阅读(38) 评论(0) 推荐(0)
摘要:原题链接 题解 做两遍dfs,就能从树中求得图的效果了 第一遍,令 \(f[i]\) 为以 \(i\) 为根的子树(包括自身)的 \(maxans\) 则 \(f[i]\) 的初值为 \( \begin{cases} 1,a[i]=1 \\ -1,a[i]=0 \end{cases} \) \(f[ 阅读全文
posted @ 2024-03-19 21:47 纯粹的 阅读(18) 评论(0) 推荐(0)
摘要:原题链接 题解 对于一个圆而言,如果两个点都在其内或其外,那么这个圆是不会经过的 所以穿过的圆是其中一个点在里面,另一个点在外面 code #include<bits/stdc++.h> using namespace std; struct node { int x,y,r; }circle[10 阅读全文
posted @ 2024-03-20 12:15 纯粹的 阅读(48) 评论(0) 推荐(0)
摘要:原题链接 题解 有点思维,已知一个交点不会有三条对角线经过,所以有且只有两条对角线经过,而两条对角线又对应四个顶点,所以变成了组合数学,n个顶点里取四个。 为了防止溢出,这里做了一些处理 code #include<bits/stdc++.h> using namespace std; int ma 阅读全文
posted @ 2024-03-20 12:29 纯粹的 阅读(35) 评论(0) 推荐(0)
摘要:原题链接 题解 1.将雷达建在海岸线上最优,覆盖的面积最大 2.根据光线可逆,雷达安装的位置覆盖多少小岛,等价于小岛被覆盖需要在哪个范围的位置上安装雷达 3.想象把雷达安装在最左边,然后慢慢往右移,这个时候雷达覆盖的小岛数量会越来越多,当右移到某个原本能覆盖的小岛覆盖不了时,在那个位置安装一个雷达 阅读全文
posted @ 2024-03-20 18:01 纯粹的 阅读(102) 评论(0) 推荐(0)
摘要:原题链接 题解 想象一下,从左上角无限大的地方开始,第一个看到的一定是斜率最小的且截距最大的,慢慢往右下角滑,第一个碰到的直线一定是斜率比前一个小(不一定是第二小)的但是是它的斜率所属直线里截距最大的 重复上述步骤,最外面的直线一定长这样 图片来自luogu,linaonao 所以我们可以按斜率排序 阅读全文
posted @ 2024-03-20 21:24 纯粹的 阅读(38) 评论(0) 推荐(0)
摘要:原题链接 题解 1.我们可以用若干条直线把所有点串起来,串起来的要求是不同直线不共点,这样以每条直线上的两点为底,直线外另一点为顶点配对 令最大的直线上的点数为k,如果n-k>=k/2+k%2,那么这条直线上的点一定可以被消除。否则不行 就变成了若干集合彼此相消,当最大集合大小超过剩余集合总和时无法 阅读全文
posted @ 2024-03-23 15:53 纯粹的 阅读(29) 评论(0) 推荐(0)
摘要:原题链接 题解 考虑以下决策,绝对最优: 1.按巧克力块的大小排序,先把大的块分出来。 2.一开始完整的巧克力是块矩形,取出一个正方形后,可以分为下方和右侧两个矩形,然后把这两个矩形放入优先队列。 3.分割下一个矩形时,从队列中取出 最短边最长的那个矩形,在这个矩形上做步骤2一样的分割 为什么这样的 阅读全文
posted @ 2024-03-25 13:56 纯粹的 阅读(47) 评论(0) 推荐(0)
摘要:原题链接 题解 太巧妙了!! 层加式? code #include<bits/stdc++.h> #define ll long long using namespace std; ll a[100005]={0}; int main() { ll t; cin>>t; while(t--) { l 阅读全文
posted @ 2024-03-27 17:33 纯粹的 阅读(26) 评论(0) 推荐(0)
摘要:原题链接 题解 1.异或是01变1,11变0,或是01变1,11变1,所以或的越多(即分的组越多),结果越大 2.我们令x=x+1,这样小于等于x的 问题就变成了小于x 的问题,这里我们采用逼近答案的方法。 3.对于某一位而言,如果有奇数个元素在这一位上是1,那么不管怎么分,最后的结果肯定是1,如果 阅读全文
posted @ 2024-03-27 21:37 纯粹的 阅读(77) 评论(0) 推荐(0)
摘要:原题链接 题解 1.由于没有指向外面的箭头,所以 \((1,1)\ (1,2)\) 都是 > 2.每次移动两步,所以落点一定是距离原点曼哈顿距离为偶数的点,所以中转点一定是曼哈顿距离为奇数的点,所以枚举所有曼哈顿距离为奇数的点(不包括终点),只要其没有连续出现<,一定能过去 code #includ 阅读全文
posted @ 2024-03-27 21:59 纯粹的 阅读(138) 评论(0) 推荐(0)
摘要:原题链接 题解 1.每个城市选择一个与它最近的城市 2.如果三个或以上的城市申请修建的公路成环。如下图,A 申请修建公路 AB,B 申请修建公路 BC,C 申请修建公路 CA。则政府将否决其中最短的一条公路的修建申请; 但是这条不成立,请看这条题解 或者下图 由此得出这题就是最小生成树,虽略有不同, 阅读全文
posted @ 2024-03-28 16:34 纯粹的 阅读(33) 评论(0) 推荐(0)
摘要:原题链接 题解 1.看到数据范围很小,所以我们可以穷举 如何穷举呢? 三个方向的背包dp,令 \(dp[i][j][k]\) 来表示 三边长度为 \(i,j,k\) 时能否达到,然后最外面一维是所用的木板 由于她想用所有的木板 所以 \(k=total-i-j\) ,所以可以变成两维 注意这里的背包 阅读全文
posted @ 2024-03-28 18:06 纯粹的 阅读(55) 评论(0) 推荐(0)
摘要:原题链接 题解 1.选k个数,就会有k-1个数没法选。我们可以倒着来,每少选一个数,就会多一个数可以选,添加总比删除简单 2.最小的那个数,也就是第k小的数,因此我们可以维护一个大小为k 的优先队列,最小值就是队首元素 code #define ll long long #include<bits/ 阅读全文
posted @ 2024-03-28 21:23 纯粹的 阅读(29) 评论(0) 推荐(0)
摘要:原题链接 题解 1.要确保任意回合赢回来的钱都要比之前下注的钱的总和要多 令 \(b_i\) 为第 \(i\) 回合下注的钱,则有 \(b_i·k>\sum_{j=1}^{i}b_j\) 则有 \(b_i\ge \left\lfloor \frac {\sum_{j=1}^{i-1}b_j}{k-1 阅读全文
posted @ 2024-03-28 22:04 纯粹的 阅读(31) 评论(0) 推荐(0)
摘要:原题链接 题解 1.看到拼接,有种背包dp的感觉 所以方法1,暴力背包dp \(Code1\) #include<bits/stdc++.h> using namespace std; int vis[200005]={0}; vector<string> a; int main() { strin 阅读全文
posted @ 2024-04-01 22:51 纯粹的 阅读(125) 评论(0) 推荐(0)
摘要:原题链接 题解 1.这k个城市一定是连成一团在中间的 2.把树展开,变成散发图,剩下的n-k个城市一定在最边缘的位置 3.拓扑排序 dalao's blog code #include<bits/stdc++.h> using namespace std; vector<int> G[100005] 阅读全文
posted @ 2024-04-02 19:19 纯粹的 阅读(323) 评论(0) 推荐(0)
摘要:原题链接 题解 树上只有两种颜色,我们把每种颜色的连通块记录下来,只有当路径两端的点属于同一连通块且颜色与朋友喜欢的不同时输出0 code #include<bits/stdc++.h> using namespace std; char s[100005]; int fa[100005]; int 阅读全文
posted @ 2024-04-02 19:37 纯粹的 阅读(42) 评论(0) 推荐(0)
摘要:原题链接 题解 1.当 \(s_2\) 长度大于等于 \(s_1\) 时,我们就令 \(s2\) 的长度为 \(n\) 2.当 \(len(s_2)<n\) 时,我们令此时的 \(s_2\) 无法被自我链接形成,为什么要这么设? 3.此时的 \(s_1\) 与 \(s_2\) 的关系一定张这样,为什 阅读全文
posted @ 2024-04-04 12:33 纯粹的 阅读(62) 评论(0) 推荐(0)
摘要:原题链接 题解 1.Q是S的前缀 2.Q!=S 3.S是QQ的前缀,且S可以等于QQ 4.从S中挖掉Q后剩下的部分与Q(s)的前半部分重合,也就是公共前后缀 5.要让Q尽可能长,就要让公共前后缀尽可能短(非零) 细节请看代码 解答一些疑惑:为什么不能直接求最短公共前后缀,而是要先求最大公共前后缀? 阅读全文
posted @ 2024-04-04 16:22 纯粹的 阅读(31) 评论(0) 推荐(0)
摘要:原题链接 题解 我一直苦苦思考为什么要建边,现在我明白了,如果令 \(x_i\) 代表离源点的最短路径长度的话,建边之后,\(x_i-x_j<=y_k\) 一定成立 只有当出现负环的时候说明条件出现了矛盾 太神了 为什么负环会出现矛盾? 简单认识一下,如果出现负环,代表每到一个点就至少有一条边的约束 阅读全文
posted @ 2024-04-04 21:16 纯粹的 阅读(62) 评论(0) 推荐(0)
摘要:原题链接 题解 模拟,遍历n个物品,一开始一个箱子不给,遍历到某个物品时,先把所有已经给了的箱子放进去试试,再创一个新箱子放进去试试 code #include<bits/stdc++.h> using namespace std; int n,w; int cnt,ans; int chongdi 阅读全文
posted @ 2024-04-05 14:49 纯粹的 阅读(28) 评论(0) 推荐(0)
摘要:原题链接 题解 巧妙模拟题 1.\(n\leq 5000\) 所以可以暴力枚举k 2.把翻转的区间具象化,我们可以发现序列中值为 1 的地方覆盖了偶数个区间, 0 的地方覆盖率奇数个区间 所以我们遍历字符串的时候,在遇到的第一个0开始建立以其为左端点的区间,如果遇到 1 的区间覆盖数为奇数,那就再建 阅读全文
posted @ 2024-04-09 16:41 纯粹的 阅读(204) 评论(0) 推荐(0)
摘要:原题链接 题解 每一个任务都有一个最小起点能力值,和通过任务后获得的能力值,我们从最小起点开始遍历,如果遍历到某一点累加的能力值+最小起点能力值够不到当前任务的最小能力值,我们把最小起点向右移动直至够到当前任务的最小能力值。 code #include<bits/stdc++.h> using na 阅读全文
posted @ 2024-04-09 21:22 纯粹的 阅读(27) 评论(0) 推荐(0)
摘要:原题链接 题解 不仅要学会怎么打cf,还要学会怎么解决问题:把条件写下来,对着条件写,然后对着程序在脑海中充分模拟 code #include<bits/stdc++.h> using namespace std; char s[20005]; int main() { int t; cin>>t; 阅读全文
posted @ 2024-04-09 23:03 纯粹的 阅读(33) 评论(0) 推荐(0)
摘要:原题链接 题解 设 \(a,b,c,d\) 分别为 \(1,2,3,4\) 的个数 则对第一位贡献 \(a+c\) 个1 对第二位的贡献为 \(b+c\) 个1 对第三位的贡献为 \(d\) 个1 根据异或原理,奇数个一异或还是一,偶数个一异或是零 所以 \(a,b,c\) 同号, \(d\) 是偶 阅读全文
posted @ 2024-04-10 15:56 纯粹的 阅读(255) 评论(0) 推荐(0)
摘要:原题链接 题解 \(gcd\) 一定能被 \(a[1][1],a[n][m]\) 整除 2.\(gcd\) 能被通过的路径上所有元素整除 由此分析:遍历 \([1,\sqrt{gcd(a[1][1],a[n][m])}]\) 判断能否通过(被路径上所有元素整除) 我还在思考是广搜还是深搜,由于起点终 阅读全文
posted @ 2024-04-10 16:49 纯粹的 阅读(147) 评论(0) 推荐(0)
摘要:原题链接 题解 假如一开始是一个完全单调递增函数,那么没有任何链接,这时我们交换两个数 \(i,j\),则 \([i,j]\) 成了一个连通块,这时我们再取出 \([i+1,j]\) 内的元素与 \(l,l \in[j+1,n]\) 交换,则 \([j,l]\)成了一个连通块 所以 \([i,l]\ 阅读全文
posted @ 2024-04-10 20:28 纯粹的 阅读(29) 评论(0) 推荐(0)
摘要:原题链接 题解 观察数据范围,看到 \(n<=5000\) 便确定了 \(O(n^2)\) 左右的算法,这样一来我可以遍历所有的区间 虽然每个 \(f(k)\) 对应的答案区间都不同,但一定能遍历到,所以我可以再遍历一遍k,算出以该区间为答案区间时的 \(f(k)\) 但是这样一来时间复杂度就超了, 阅读全文
posted @ 2024-04-10 21:14 纯粹的 阅读(35) 评论(0) 推荐(0)
摘要:原题链接 题解 设想每一个 \(x,y\) 代表中控台,中控台颜色改变它控制的颜色也会跟着改变,我们倒过来求,这样就能确保每个中控台有没有控制的颜色 code #define ll long long #include<bits/stdc++.h> using namespace std; cons 阅读全文
posted @ 2024-04-12 11:28 纯粹的 阅读(25) 评论(0) 推荐(0)
摘要:原题链接 题解 如果存在某一条边的 \(a_i>=2*(sum-a_i)\) 那么这条边一定有点剩余无法连接,为什么?这条边上每取两个点作为底边点,就一定能去外面一个点作为顶点,且无交叉(顺时针或逆时针) code #include<bits/stdc++.h> #define ll long lo 阅读全文
posted @ 2024-04-12 11:49 纯粹的 阅读(55) 评论(0) 推荐(0)
摘要:原题链接 题解 具体想 \(a\) 是如何一步一步变成 \(b\) 是很复杂的,所以我们换个角度思考(比如贡献) 遍历每一个 \(a[i]\) 看看他们能帮助哪些 \(a[j]\) 变成 \(b[j]\) 而且不妨碍 \((i,j)\) 中 \(a\) 的元素,用数学语言表达就是 \(use[j]= 阅读全文
posted @ 2024-04-12 14:38 纯粹的 阅读(61) 评论(0) 推荐(0)
摘要:原题链接 题解 1.突然遇到新颖的题,我们可以采用逐步变难法、最简策略法、观察数据法 逐步变难法: 当 \(k=0\) 时, \(ans_0=min(a[i])\) \(k=1\) 时 \(ans_1=min(ans_0,a[i]-a[i+1](sort))\) 观察数据法: \(k=2\) 时 观 阅读全文
posted @ 2024-04-12 15:14 纯粹的 阅读(13) 评论(0) 推荐(0)
摘要:原题链接 题解 只需要存在两个叶子节点之间距离等于d就好了,于是我们构造一条链,令节点一为滑动变阻器,则根据d改变与节点n的距离即可 code #include<bits/stdc++.h> using namespace std; int main() { int t; cin>>t; while 阅读全文
posted @ 2024-04-12 18:46 纯粹的 阅读(14) 评论(0) 推荐(0)
摘要:原题链接 题解 1.最小数在操作之前是第一位,操作之后也必然是第一位,这就导致了如果原数组最小数后的数遍历不到,如果非有序就真的没法有序了,否则每个数都刚好大于前面一个数一定有序 code #include<bits/stdc++.h> using namespace std; int a[2000 阅读全文
posted @ 2024-04-12 19:12 纯粹的 阅读(51) 评论(0) 推荐(0)
摘要:原题链接 题解1 本质:求一个数前面有几个数大于它,我们把序列分成几段,然后对每段分别进行排序,然后找出这个数在前面已经排好序中的序列里有几个大于它 code #include<bits/stdc++.h> using namespace std; #define ll long long ll a 阅读全文
posted @ 2024-04-13 13:24 纯粹的 阅读(49) 评论(0) 推荐(0)
摘要:原题链接 题解 \(O(n^2)\) 不可能,所以考虑线性,将奶牛按下标排序,顺序遍历,对于 \(i\) 而言,它的贡献等于 \(\sum_{j\lt i\ ,\ v[j]\leqslant v[i]}{dis(i,j)·v[i]}\) ,等于 \(v[i]·((\sum_{j\lt i\ ,\ v 阅读全文
posted @ 2024-04-15 12:28 纯粹的 阅读(89) 评论(0) 推荐(0)
摘要:原题链接 题解 1.把字符串离散成数字(总不可能有重名的吧) 2.树状数组计算逆序数(比归并排序好写多了),即计算小于 \(i\) 的数的出现次数总和 code #include<bits/stdc++.h> #define lowbit(x) ((x)&(-x)) using namespace 阅读全文
posted @ 2024-04-15 12:42 纯粹的 阅读(35) 评论(0) 推荐(0)
摘要:原题链接 题解 极端试探法,既然要求 k 的最大值,k 最大为 n,当 k 能取 n 是什么时候?是所有数都相等的时候。 k能不能取n-1?能,给n-1个数同时乘上一个数,等价于剩下的那个数除以一个数(相对大小),而把所有数都除到1,它们就相等了 举例: 2 3 4 5 给后面3个数同时乘上2 \( 阅读全文
posted @ 2024-04-15 16:07 纯粹的 阅读(39) 评论(0) 推荐(0)
摘要:原题链接 1.极限构造法 ,黑珠数量 \(\geqslant\) \(max(y_i)\) , 白珠数量 \(\geqslant\) \(max(x_i-y_i)\) 再观察样例,发现刚好把1全部放左边,0全部放右边时等号成立 code #include<bits/stdc++.h> using n 阅读全文
posted @ 2024-04-15 16:28 纯粹的 阅读(178) 评论(0) 推荐(0)
摘要:原题链接 题解 本题虽然有思维题做法,但是我认为不具有普世意义,本题的特点在于分治法,即普通算法在平均条件下表现良好,但是在极端条件下极慢,这时候我们需要将极端条件拎出来另做判断 code #include<bits/stdc++.h> #define ll long long using name 阅读全文
posted @ 2024-04-16 11:18 纯粹的 阅读(39) 评论(0) 推荐(0)
摘要:原题链接 题解 1 看代码,最简单的 这叫什么思想?不知道,我暂时叫做信息标记法,但是标记的角度清奇 code1 #include<bits/stdc++.h> using namespace std; int late[100005]={0};//离自己最近的相同元素的位置 int maxleft 阅读全文
posted @ 2024-04-16 12:14 纯粹的 阅读(31) 评论(0) 推荐(0)
摘要:原题链接 题解 本题的优化真的很重要!! 把所有元素出现的下标用map套vector存起来,然后二分查找 code #include<bits/stdc++.h> using namespace std; map<int,vector<int> > mp; int main() { ios::syn 阅读全文
posted @ 2024-04-16 12:49 纯粹的 阅读(119) 评论(0) 推荐(0)
摘要:原题链接 题解 ,太不容易了 \(a_i!=a_j\) 所以对于每一个数而言,最多有两个配对,最少有一个配对。即排序之后,前后哪个离自己更近就和谁配对 \((x,y)!=(y,x)\) 把配对看成区间 令 \(tree[i]\) 代表有多少个区间的左端点大于 \(i\) 把查询按右端点排序,顺序遍历 阅读全文
posted @ 2024-04-17 15:42 纯粹的 阅读(78) 评论(0) 推荐(0)