如何优雅地压行

· · 个人记录

大型邪教传播现场(并不是

本篇文章将教你如何优雅的压行,在保证代码可读性的情况下使代码长度尽量缩短。

先丢一份快读(真的很快

inline int read(int t=0, bool f=1, char c=0) {
    while(!isdigit(c=getchar())) f=c^45;
    while(isdigit(c)) t=(t<<1)+(t<<3)+(c^48), c=getchar();
    return f? t: -t;
}

几个常用的技巧

什么是短路

C++ 里的逻辑运算符 &&|| 拥有一种叫做“短路”的特性。设计本意应该是加快效率,但是可以用来压行。

&& 连接的语句会从左往右判断,一旦有 false 语句出现,右边的所有语句都会被短路掉,不会被运行。同理,用 || 连接的语句中一旦有 true 语句出现,右边的语句也同样不会运行。

所以 &&|| 可以一定程度上代替掉 if else。例如 if(acbc) puts("acttbc"); 可以写成 acbc&&(puts("acttbc"), 1);

这时候就有人要问了,“那它有什么用呢?我还不如用 if else,还不用注意语句返回值!”

因为 && || 可以用 , 和其他语句连成一行啊!我们举个简单的例子。

void dfs(int u) {
    int v, siz=0, mx1=0, mx2=0;
    rep(d, 0, 25) if(v=son[u][d]) {
        dfs(v), siz+=cnt[v];
        if(mx1<dp[v]) mx2=mx1, mx1=dp[v];
        else if(mx2<dp[v]) mx2=dp[v];
    }
    if(cnt[u]) dp[u]=mx1+max(siz, 1);
    ans=max(ans, mx1+mx2+cnt[u]+max(siz-2, 0));
}

使用 && || 压行后:

void dfs(int u) {
    int v, siz=0, mx1=0, mx2=0;
    rep(d, 0, 25) if(v=son[u][d]) dfs(v), siz+=cnt[v], mx1<dp[v]&&(mx2=mx1, mx1=dp[v], 1) || mx2<dp[v]&&(mx2=dp[v]);
    cnt[u]&&(dp[u]=mx1+max(siz, 1)), ans=max(ans, mx1+mx2+cnt[u]+max(siz-2, 0));
}

其中两个 if 语句都和其他语句合并成了一行。

define 到底有什么有趣的用处

define 里可以塞一些“变量”,例如大家常用的 #define max(a, b) ((a)>(b)? (a): (b))#define lowbit(x) ((x)&-(x))

##define 里的连接符:它可以将两个常量字符串或变量字符串链接。于是我们可以写一个这样的 define 句子: #define rep(i, a, b) for(int i=(a), i##up=(b); i<=i##up; ++i)

这个句子可以和快读组合使用,缩短代码中较为次要的输入部分的码量。

rep(i, 1, n=read()) a[i]=read();

而不用写像这样两行

scanf("%d", &n);
for(int i=1; i<=n; ++i) scanf("%d", &a[i]);

又比如一个这样的句子 #define ree(e, u) for(int e=ehead[u], v=eto[e]; e; v=eto[e=enxt[e]]),可以有效缩短搜索的码量。

void dfs(int u, int fa) {
    ree(e, u) if(v!=fa) dfs(v), ...;
}

“用 , 连接的几个语句的返回值是最后一个语句”有什么用

事实上,上一个部分的未压行部分还是可以压行的

for(int i=1, iup=(scanf("%d", &n), n); i<=iup; ++i) scanf("%d", &a[i]);

注意 (scanf("%d", &n), n) 这一句,它的返回值是 n

你知道吗,void 类型的句子也是可以作为返回值的,甚至可以丢到 return 后面。也可以用一个空的 void() 来代替一般的 void 语句。

//线段树更新操作
int sum[SN], tag[SN];
void updata(int p, int v, int len) { sum[p]+=v*len, tag[p]+=v; }
void modify(int p, int le, int ri, int dl, int dr, int dv) {
    if(dl<=le&&ri<=dr) return updata(p, dv, ri-le+1);
    ...
}
//dfs 回溯
void dfs(int u) {
    mk[u]=1;
    ree(e, u) {
        ...
        if(...) return mk[u]=0, void();
        ...
    }
    mk[u]=0;
}

就这样吧(?)

华丽的压行技巧并不能提升代码水平,只有不到位的压行技巧导致爆零。希望这篇文章能帮到你(并不)。当然每个人的码风都是不同的,本文并不提倡压行,只是希望喜欢压行的 OIers 可以通过本文提升自己的压行技术。