博文

目前显示的是 2019的博文

如何优(装)雅(B)地使用C++

介绍一些冷门的C++语法特性,供压行选手使用(雾) 前置知识 C++基础语法( 运算符重载 template 的初级应用(什么是初级呢,会用 template 写 max 就好) functor (只会提及,了解即可) 正文 1.匿名函数(lambda表达式) 需要C++11 比赛可用:★★★☆☆ 代码简化:★★★★☆ 匿名函数应用于需要使用短函数的场合,或者函数需要修改此作用域内(非全局作用域)的局部变量的场合。 常见用法是使用 sort 的时候,需要传入一个 cmp 数组,但是自行定义又太过于繁琐,这时候可以直接使用 lambda 表达式。 基础格式: [捕捉局部变量列表](参数){函数体} 例如,如果需要给 point 排序,以 x 为第一关键字从大到小排序,可以这么写: sort(pi+ 1 ,pi+ 1 +n,[](point a,point b){ if (a.x != b.x) return a.x<b.x; return a.y<b.y; }); lambda 本质是一种 functor ,即重载了 operator () 的类。 笔者曾经想使用 lambda 表达式作为返回值,然后就不想了 笔者曾经想使用 lambda 表达式来玩一些骚操作,然后被类型系统劝退了 2.语句内嵌表达式 无特殊要求 比赛可用:★★★★★ 代码简化:★★☆☆☆ 语句内嵌表达式应用于需要在传入一个值的场合运行一个表达式的情况。这么说可能有点抽象,具体来说,比如我们要执行以下程序段: int a = query( 1 , 1 ,n,l1,r1); int b = query( 1 , 1 ,n,l2,r2); printf ( "%d" ,a+b+a*b); 这时候,就可以使用这样的语法来代替: printf ( "%d" ,({ const int a = query( 1 , 1 ,n,l1,r1); const int b = query( 1 , 1 ,n,l2,r2); a+b+a*b; })); 也就是说,语句内嵌表达式的格式是这样子: (

你不知道的C++11新语法

图片
随着C++11的发布,C++这门语言有了本质上的提升。C++14,C++17的相继推出,更是让C++这门语言达到了一个新高度。新的标准库设施,新的语法,让我们得以书写更加安全、便捷、高效的程序。 2018年6月编程语言排行榜: 那么这些新的语法究竟是什么?它们如何使用?能为我们编程带来哪些便利?这便是本文所探讨的。 本文参考部分资料,文末已给出原文章地址。 新的空指针类型——nullptr 适用度:★★★★★ nullptr是一种特殊的字面值,它可以转化为任意一种指针类型。 原来我们初始化一个空指针都是直接将他赋值为NULL, 但NULL实际上是一个宏,其值相当于0 。 编译器是这么定义NULL的: # ifdef __cplusplus //如果定义__cplusplus宏,说明正在编译C++语言 # define NUll 0 # else # define NULL ((void *)0) # endif 也许你会想“我们用NULL还不是照样 吊打集训队 ”,nullptr好像并没有什么用。 考虑这样一段代码: int f ( int x) { //do something } int f ( int *x) { //do something } int main () { f( NULL ); } 很显然,编译失败,对f的调用有二义性。因为NULL相当于0,既可转化为指针,也可转化为整形。将NULL换做nullptr即可,nullptr便是为了解决这种二义性的问题而诞生的。 条件允许的前提下,尽量使用nullptr,它比NULL更加安全, 原来这样写: int a = NULL ; int *b = NULL ; 现在应该这样写: int a = NULL ; int *b = nullptr ; 避免奇葩错误——constexpr变量 适用度:★★★★☆ 在编程中,我们经常遇到需要定义常量的情况,但有些常量却并不是你所想的“常量”。因而会引发一些意想不到的错误。 例如: int a; const int b = a + 10 ; int c[b]; //错误,b不是一个常量表达式,它的值每次运行都有可

【洛谷】题解 CF1277E【Two Fairs】

图片
题目大意 给出一张无向图以及两个点 a,b ,之后您需要求出有多少对点对 (u,v) 满足从 u 到 v 的任意一条路径都必须同时经过点 a,b 。 同时若 (u,v) 中的任何一个点为 a 或 b ,则这个点对也不合法。 n <= 1e5 吐槽 虽然确实挺有意思,但是这么简单的题,出到 Div2E 我觉得有点不合适吧QAQ。 另外这一篇题解中您可能会大量看见某些词的重复使用。 题解 我们从 a 点开始bfs,对所有到达的点染色一次,同时要求此时不能经过 b 。 之后从 b 点开始bfs,对所有到达的点染色一次,同时要求此时不能经过 a 。 此时我们应当有三类点:只被 a 染色、只被 b 染色、同时被 a,b 染色,由于图是联通的,所以不会存在没有被染色的点。 答案是第一类点的数量乘上第二类点的数量。 证明 我们考虑一对合法的点 (u,v) ,为方便起见我们假设 u 是第一类点而 v 是第二类点。 之后我们思考一下 u 只被 a 染色的意义是什么。 实际上这意味着 u 可以通过某些方式到达 a ,但它不能通过 a 以外的任何点到达 b ,换句话而言若 u 想有一条到 b 的路径,那么其路径上必须经过 a 。 实际上 v 只被 b 染色的意义是相似的。 之后我们想证明什么? 我们想证明任何一条从 u 到 v 的路径都必须经过 a,b 。 我们讨论一下一条从 u 到 v 的路径的情况。 实际上我们只需要考虑一下是否可以存在不同时经过 a,b 的路径的可能性就好了。 具体来说,我们假设存在一条路径使得其不经过 b ,那么应当有: 从 v 能不经过 b 到达 u 。 u 能不经过 b 到达 a 。 从 v 能不经过 b 到达 a 于是我们发现此时出现了矛盾,第二类点实际上是不能通过 b 以外的点到达 a 的,于是不可能存在这样一条路径。 证明不存在一条路径使其不经过 a 也可以用相同的方法证明出来。 于是我们就证明了至少有这么多点对是可行的。 之后我们还需要证明其他的点对是不可行的。。 实际上这里的证明和上面的证明也是相似的所以略过。 然后就把这个做法的正确性证明出来了~ 代码 #include   <b