刷题笔记
这里呢会有一些我认为比较提供思路,但是又不是特别重要的内容、
易错整理
1.。假如一个变量在循环里会变,那么这个循环的条件一定要想好是不是可以用这个变量
2。 一道题正着作难不妨想一想反着做
p2700
这个就是一个正着作难,反着好做,其实和星球大战很想,就是最大生成树的思路,每一次拿出的边看看左右端点的祖先是不是敌人,注意这里一定要是祖先,假如我们只对单独点去进行判断,那么在一堆我方点连在一起后,有连了一个敌人,那么这一个链都不可以连敌人了,所以一定是对于祖先的操作,最后并查集维护就好。
P2827
这是一道要去分析题目里面的信息的题目,其实我们最开始发现每一次切完蚯蚓后都要去给每一个加上一个数,但是这显然复杂度过高,所以我们就反着做,每一次把切开的数字减去要加的数,最后在记录一下一共要加几次(注意每一次找到要切的数的时候还要加上这个),现在对于这个的处理已经不是问题了,最后就是维护最大值,最简单的是用priority_queue但是复杂度显然会大,这是我们就要去发现题目的性质,** 假如两条蚯蚓最开始的长度a>b,那么a一定会先被切(显然),之后又可以轻易的发现这个a切完后的长度一定还是比b切完后的长,** 证明 假如a切成了 xa-----(1-x)a 在z回合后b被切
a的两个就变成了xa+bq------(1-x)a+bq;
b的两个就是 x(b+bq)-----(1-x)(b+bp);
这里的他们被切开的那一段,不用加长度,可以相互抵消,就不理了。就类似会变为这样,然后显然就可以发现题目中自带的单调性,所以就可以用三个数组去维护,最开始的,第一个切开,第二个切开,最后在记录一共要加多少次就欧克了。
** 其实这道题告诉我们,要去发现题目的性质,和正难做就反着做,比如像是去边,和加法**
合并果子加强版
这个就是利用一下桶排序的思想,
** 就是假如这个数出现过,则tong[a]++就表示a这个数现在有一个,最后在去遍历每一个数就可以完美的排好序**
(显然,只适用于数据大小比较瘦小的题目),这个的话是比较快的,最后就只用维护两个单调对列,一个是之前的,一个是合并后的,其实也不用维护,因为合并后的肯定自己就满足单调性。
CF1542B
这是一道比较好的思维题,其实最开始我没有发现这个,首先他所谓的x可不只是1,而是衍生出来的所有的x,所以不可以单单的判断是否的a/b的倍数,之后我们就像一下这种方式得出的x的通式是啥,其实有两种
但是转化一下就是一种了
所以就看看n是不是1式
how----》 其实我们可以用一下简单的取模(毕竟有这么多的倍数,不取模是不是对不起这个形式)。
就好了,只要倍增的去判断,复杂度也可以接受。
P7339
这题本来我是想用贪心去完成,但是发现不但时间复杂度不好,而且wa声一片,就看了一看题解,终于理解了,首先贪心不对在于假如有a,b,c这三个选手,其中a是bc下一轮的敌人,之后看图
这样就反驳了贪心的做法
正解其实是分治,就是假如我们找出来最后可能获胜的所有人是不是就可以一波判断是否有1,那么我干什么是不是只用去递归找每一个赛区所有可能胜出的人,之后和另一个赛区去比较,同时淘汰人,如图
所以说做法就呼之欲出了,其实就是归并排序的思想,在排序的同时存下每一个可能获胜的人的编号,最后就只用遍历一遍答案数组,看看有无1就OK
代码中有注释
#include<bits/stdc++.h>
using namespace std;
void read(long long &x){
int r=0;
char s;
s=getchar();
while(s>'9'||s<'0') s=getchar();
while(s>=