压行宝典

news/2024/10/3 10:15:25

本人实力不济,如有错误(或其他建议),欢迎指出。

压行宝典

压行是个好东西,本文将以luoguP5661(本代码提交0分)和其余零碎代码为例,向你讲解如何正确压行

原版未压行(格式化邪教):

#include<bits/stdc++.h>
using namespace std;
int opt,n,ans,top,m=1,k;
int t[100010],p[100010],yh[100010],sj[100010];
bool r[100010];
int main() {cin>>n;for(int i=1; i<=n; i++) {cin>>opt>>p[i]>>t[i];if(opt==0) {yh[++top]=p[i],sj[top]=t[i],ans+=p[i];} else {k=0;for(int j=m; j<=top; j++) {if(r[j]) continue;if(t[i]+sj[j]>45) m=j;else if(yh[j]>=p[i]) {k=j;r[k]=true;break;}}if(!k) ans+=p[i];}}cout<<ans;
}

0.为什么压行

  • 技术含量不高
  • 使代码更短
  • 可读性更高
  • 方便调试

虽然格式化邪教也有着不少优点,但是它缺少了动手完成的成就感 ,而且,压行,是神教,正道!!!!!!!!!!!!!!!!!!!!!!!

有人说

华丽的压行技巧并不能提升代码水平,只有不到位的压行技巧导致爆零。

但是,压行可以保证代码的可读性

I.压行基础

I.I 逗号的使用

当多条赋值语句和函数各占一行时,会让人不爽,这时,逗号出现了,他可以对其进行连接(注意,他的优先级最低,且返回最后一个值)。

原版

k=j;
r[k]=true;

压行

k=j,r[k]=true;

I.II 常数替代

原版代码的定义中我们可以发现数据范围反复出现,此时我们可以定义常量。

原版:

int t[100010],p[100010],yh[100010],sj[100010];
bool r[100010];

压行?:

constexpr int N=100010;//不建议用const
int t[N],p[N],yh[N],sj[N];
bool r[N];

I.III 删掉大括号

答括号有时候必须得用到,但是它的出现必定会使代码的行数增加三行至以上,当我们用其他压行技巧把大括号里的内容压到只有一行时,删掉他(函数不行)!

for (int i=0;i<n;i++)
{for(int j=0;j<n;j++){scanf("%d",&a[i][j]);}
}

压行for(int i=0;i<n;i++) for(int j=0;j<n;j++) scanf("%d",a[i][j]);

II. 中级压行

II.I 三目运算符

条件 ? 如果为真执行 : 如果为假执行 里面不能塞代码块哟

if else可以扔掉了,再注意一下优先级即可。

如max函数

int max(int a,int b)
{if(a>b) return a;else return b;
}

int max(int a,int b){return a>b?a:b;}

II.II 短路原理

请先看代码:

#include<stdio.h>
int main()
{int a=100,b=200;if(a>99&&b++) {if(a>200&&b=b-2) ;}printf("%d %d",a,b);return 0;
}

输出为100 201

这就是短路性质:

如果第一个条件(左边的条件)为真(true),则不会计算第二个条件(右边的条件),整个表达式被认为为真。

只有当第一个条件为假(false)时,才会继续计算第二个条件。 如果第二个条件为真,整个表达式被认为为真;如果第二个条件也为假,整个表达式被认为为假。

而例如a=b+1返回的值是计算后的a,所以通过这种方法我们可以把:

if(a%b==0)
{sum++;break;
}

改为

if(a%b==0&&++sum) break;//不要sum++防止sum的初始为0而导致条件为假

II.III 巧用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)

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

III 高级压行

III.I 巧用lambda表达式

上文中我们提到三元运算符中不能放代码块,但是lambda表达式可以。关于它的使用请自行bdfs或这边粗略看一下,没时间讲太多。

捕获变量时建议隐式引用捕获,这样你可以不用写太多。

例子:

for(scanf("%d",&n);i<=n;i++)
{scanf("%d%d%d",&opt,p+i,t+i);if(!opt) yh[++top]=p[i],sj[top]=t[i],ans+=p[i]else{func();for(k=0,f=1,j=m;j<=top&&f;j++) r[j]?1:(t[i]-sj[j]>45?m=j:(yh[j]>=p[i]&&(k=j)&&(r[k]=true)?f=0:1));if(!k) ans+=p[i];}
}

运用lambda技巧后

auto func=[&](){for(k=0,f=1,j=m;j<=top&&f;j++) r[j]?1:(t[i]-sj[j]>45?m=j:(yh[j]>=p[i]&&(k=j)&&(r[k]=true)?f=0:1));};
for(scanf("%d",&n);i<=n;i++) scanf("%d%d%d",&opt,p+i,t+i),(!opt)?yh[++top]=p[i],sj[top]=t[i],ans+=p[i]:(func(),!k?ans+=p[i]:6);

IV. 其他技巧

IV.I 压输入输出

输入时可以压行到变量的定义中(我有时候压到for循环中)的,使用逗号运算符即可(cin cout输入本质上是一个类的重载运算符)

例:

int x,y=(cin>>x,0);

由于scanf,printf函数的参数读入是依赖第一个字符串的。所以scanf("%d",&x,y=100);是可以的 此方法有时会造成爆0,取消使用

IV.II 使用工具

必备工具:压行机

注:有时候可能太卡进不去,所以建议Ctrl + S先行保存

当真的压无可压的时候可使用(所以,这往往才是压行的最后一步)

IV.III 剩余的其他

  • 主函数中int可省略,这是默认的。
  • return 0;也可以省略。
  • printf返回的是输出长度(显然不会为0)所以是return!printf("%d",ans);

结语

最后,勤加练习,你的压行便会大成:

//本代码提交0分
#include<stdio.h>
const int N=100010;
int opt,n,ans,top,m=1,k,f;
int t[N],p[N],yh[N],sj[N];
bool r[N];
int main() {int i=1,j;for(auto func=(scanf("%d",&n),[&](){for(k=0,f=1,j=m;j<=top&&f;j++) r[j]?1:(t[i]-sj[j]>45?m=j:(yh[j]>=p[i]&&(k=j)&&(r[k]=true)?f=0:1));});i<=n;i++) scanf("%d%d%d",&opt,p+i,t+i,(!opt)?yh[++top]=p[i],sj[top]=t[i],ans+=p[i]:(func(),!k?ans+=p[i]:6));return!printf("%d",ans);
}//为了代码的可读性,还未使用压行机

(如需转载,请标明出处)

本人实力不济,如有错误或其他建议(包括但不限于压行技巧),欢迎指出。

参考资料

  • 扯谈压行 作者: wuwendongxi
  • 压行导论 作者: lovely_fcukh
  • 如何优雅地压行 作者: 子丑

压行万岁

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/67298.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

在树莓派上部署yolo模型推理并使用onnx加速

首先在这里感谢一下这位大佬:学不会电磁场的个人空间-学不会电磁场个人主页-哔哩哔哩视频 (bilibili.com) 这里使用的代码是从手把手教你使用c++部署yolov5模型,opencv推理onnx模型_哔哩哔哩_bilibili处来的我这里只记录下更换成自己的模型的应用以及提供一份全注释的版本树莓…

Redis 发布订阅模式

概述 Redis 的发布/订阅是一种消息通信模式:发送者(Pub)向频道(Channel)发送消息,订阅者(Sub)接收频道上的消息。Redis 客户端可以订阅任意数量的频道,发送者也可以向任意频道发送数据。在发送者向频道发送一条消息后,这条消息就会被发送到订阅该频道的客户端(Sub)…

01-什么是逻辑?

感觉 知觉 感性认识 理性认识 感觉 知觉 表象 形象思维 ==》概念 在感性认识的基础上,人们通过抽象与概括,舍弃个别事物表面的、次要的属性,而把握住一类事物特有的、共同的、本质的属性,于是就形成了反映事物的概念。 直观性与个别性是感觉、知觉与表象的特点;抽…

十五款好看的键帽,总有一款适合你✔

在客制化键盘的时候,发现了不少挺好看的键帽,特地来分享一波。在客制化键盘的时候,发现了不少挺好看的键帽,特地来分享一波。 不含广告哈,只会列出一些搜索关键词,可以在各大电商搜索查到。 如果你已经有了键盘,也可以看看是否支持拆卸键帽,偶尔换换键帽调整心情。 PS:…

10-入侵检测技术原理与应用

10.1 入侵检测概述 1)概念 20世纪 80年代初期,安全专家认为: “入侵是指未经授权蓄意尝试访问信息、篡改信息,使系统不可用的行为。” 美国大学安全专家将入侵定义为 “非法进入信息系统,包括违反信息系统的安全策略或法律保护条例的动作”。 我们认为,入侵应与受害目标相…

Nexpose 6.6.271 发布下载,新增功能概览

Nexpose 6.6.271 发布下载,新增功能概览Nexpose 6.6.271 for Linux & Windows - 漏洞扫描 Rapid7 Vulnerability Management, release Sep 26, 2024 请访问原文链接:https://sysin.org/blog/nexpose-6/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org您的…

在树莓派上安装c++版本的opencv并运行

这里默认你用的是树莓派的镜像(因为ubantu对树莓派的性能占用有点大) 树莓派安装使用 opencv c++版本 首先我们安装依赖sudo apt-get install build-essentialsudo apt-get install cmake libgtk2.0-dev pkg-config libswscale-devsudo apt-get install libjpeg-dev libpng-d…

读数据湖仓05数据需要的层次

读数据湖仓05数据需要的层次1. 业务价值 1.1. 技术和商业在这个世界上是相互交织的1.1.1. 基础数据在商业和技术应用中是不可或缺的1.2. 技术的存在是为了推动商业的目标和进步,并由企业出资支持1.2.1. 当技术推动商业发展时,商业会蓬勃发展,技术也会随之繁荣1.2.2. 当技术发…