思路讲解
无向图判环模版题,做cf之前来练练手
// 如果union函数发现根本不需要合并,那么a本来就在b的这个集合内
// 说明b有两条到达a的通路即形成了环
比较重要的两句话
AC代码
union是保留字,建议改为add(意思反正是这个意思);
1 | class Solution { |
心路历程(WA,TLE,MLE……)
哈哈,第一次写力扣嘛,总归会遇到点问题,比如啥全角字符,什么union保留字,什么·······,不多赘述。
无向图判环模版题,做cf之前来练练手
// 如果union函数发现根本不需要合并,那么a本来就在b的这个集合内
// 说明b有两条到达a的通路即形成了环
比较重要的两句话
union是保留字,建议改为add(意思反正是这个意思);
1 | class Solution { |
哈哈,第一次写力扣嘛,总归会遇到点问题,比如啥全角字符,什么union保留字,什么·······,不多赘述。
主要思路与洛谷题解类似
主要思路就是先把所有点给打散,再连起来
打散比较简单,发现这个点入度≥2就持续删边
1 | for(int i=1;i<=n;++i) { |
重新连起来需要root1和root2,否则连不起来

1 | // root,root2就是根,所有的操作都是他衍生出来的 |
https://codeforces.com/contest/2029/submission/292760535
1 | #include <bits/stdc++.h> |
原来的思路是找环,删点,但发现无向图找环很麻烦,也无法满足我的需求,于是还是决定变树。
无向图找环,用dfs加dsu(并查集)
如果不太会的话建议左转去做leetcode684冗余连接
初始化要彻底
1 | vis.reset(); // 初始化 |
dp0/1/2[0] i 之后的最高评分 ,代表其中 i 次比赛是在跳过的间隔之前/之中/之后。
其实没啥好多说的,就是题解2的思路,当然我的递推公式肯定比他复杂一点
1 | #include <bits/stdc++.h> |
一次AC,dp是这样的
事实证明人还是不要太固执,我之前就是一定想要写一个搜索算法,但怎么写都TLE,即便我看了hint知道是dp,还是想写搜索,但最后一发dp AC了。怎么说呢,搜索的时间复杂度还是有点玄学,也可能是我学艺不精(bushi)。其实我感觉如果你知道这题是dp的话也不是说非常难写,毕竟我这个非常抗拒dp的写出来了嘛
我们先想一个朴素dp,一个牌可以换到n牌当且仅当他可以换到 n牌 或 之前可以换到n牌的牌(为简化,我们称之为A牌),那就把所有这些牌都遍历一下就知道能不能换到了。
当然这个朴素dp的时间复杂度就比较随缘,最坏情况可能有O(n**2),而且其实也不是很好写。
然后我们小小的优化一下(这种优化我感觉挺常见的),其实能不能换到就是看能不能换到A牌当中优先度最低的牌。
当然三个人对牌的优先度不同,我们用pair<char,int> lowq,lowk,lowj; 分别存一下A牌中在qkj中优先度最小的。
这是对他们的初始化
1 | lowq=make_pair('q',n); |
我们以这段代码为例,这个牌成功换到了A牌中q优先度最小的,q不用更新,他的优先度肯定更高。
lowk以及lowj需要更新,这个 i 牌可能比他们的优先度更小。
1 | if(pq[i]>pq[lowq.second]) { |
最后答案输出就很简单了,跳着存入ans,玩过邻接表的都不会陌生
1 | for(int i=1;i<n;i=dp[i].second) { |
提交记录
1 | #include <bits/stdc++.h> |
一个暴搜dfs代码TLE
在第11个点TLE了,加了快读也不太行
19999个撑不住了
当然这个TLE之前肯定还出了点事,最重要的是把退出条件放在最前面,而且任何退出条件后进来的全部是多余的,ans需要pop一下。
1 | if(isFind) { |
1 | #include <bits/stdc++.h> |
这题乍一看好像是二分答案,但仔细一看好像还不太对,毕竟1600,太板了也不太好。
如果这题考二分的话,题面可能是让你求这个v最大可以为多少,这个非常适合二分答案,但显然这题不是这么问的。
我看见以前qq群里有人问什么时候用二分答案(牛客最近一场小白月赛出了道这个),我个人的回答是,你看到一道觉得像的题,都可以想一想能不能用二分答案,然后想一想检查器好不好写?如果检查器复杂度太高(跑一遍就超时),或者检查器所需要的算法可以直接求出该题答案,那么就不太行。
有些时候你也不要对自己要求太高,什么看一眼就知道怎么做。一般来说出现这种情况要么这道题太板了,要么这道题相对于你来说太简单了,我个人认为遇到这种情况大概率这题都不太适合于你平时练习,反而是你要想一想才对于你有提升吧。
搞两个数组存一下,到该位置能有多少个蛋糕(一个从左到右,一个从右到左,以消除左向依赖以及右向依赖)
具体而言是这样的

那么,然后如果我们要知道Alice把 [l,r] 这块区域切给自己后,剩下的我怎么知道够不够分那?
L[],R[]现在就开始发挥作用了
剩下区间的蛋糕总数就是L[l-1]+R[r+1]
1 | // 剩下区间的蛋糕总数就是L[l-1]+R[r+1] |
写好 check( ) 剩下的事就简单了,就是用双指针去遍历每种可能的区间,不断更新答案就好了(用的事Acwing的模版)
1 | for(int i=1,j=1;i<=n;++i) { |
AC记录
1 | #include <bits/stdc++.h> |
最早我觉得是二分答案,但接着发现不对。
代码我就不放了,主要原因是这个分蛋糕的Alice不是这m个生物中的一个,如果这题考二分的话,题目可能让你求这个v最大可以为多少。
记得把数组开大点,前面提交out of bound 了

然后不要动不动return 0;
&& j≤n 是可以加的,虽然之后的i其实就进入不到这个while里了,但先前的i一定比之后的i更优秀在这种情况下(你想想看,r确定了,l越来越大,[l,r]越来越像,Alice份给自己的就越来越少)
