LOADING

加载过慢请开启缓存 浏览器默认开启

Revethere's Blog

分享一些超级有用的芝士

Could it be MAGIC~

『博客日志 & 大事祭』

2025/6/1

25.6.1 emm 好久好久没写博客了删了点东西就当重新开始吧 😉

25.10.11 压缩了博客的大部分图片,提高响应速度

MORE

『这个 mod 将重新定义视频录制...』

介绍 2025/9/28

前言

之前写过一篇『录制 & 渲染配置分享(OBS & Blur)』

后来调录制参数一直没调好过(

120fps 下的素材跑 blur 之后就会变得非常非常糊 🤬,但是提高帧速率会带来更高的占用、游戏的卡顿以及可能卡炸的素材

很难去找到一个平衡点

Lunar 最近更新的新模组 Rewind,一定程度上解决了上述的问题:

HOW TO USE REWIND ON LUNAR CLIENT

Lunar Client | Introducing Rewind

不要在意上面这张图左上角的 logo 为什么这么奇怪,扒不到高清的图拿 AI 跑的超清像素

Rewind 简介

Rewind 是一款功能全面的剪辑、录制和编辑软件,并完全集成于 Lunar Client。无需任何外部软件即可录制 Minecraft 游戏内容

Rewind 提供广泛的功能。与大多数编辑软件一样,可以导入视频媒体,并进行组织和修剪。该 mod 专为 Minecraft 和 Lunar Client 量身定制

如何导出

Rewind 设置

启动界面进入 Rewind Editor:

选择你刚才的 Recording,创建项目

分辨率(Resolution)建议选择你玩游戏时的分辨率,不然 ui 大小会变,非常难受 ):):):

帧率(framerate)建议直接拉满,毕竟后续还要变速

进入后在 Properties 功能区中将 Speed 选项拉到 0.25(根据情况而定,拉的越低后续渲染会更舒服,但是导出时间也会更长)

时间对比

电脑配置:

  • CPU : Intel(R) Core(TM) Ultra 9 285H
  • GPU : NVIDIA GeForce RTX 5080 Laptop GPU

开启性能模式

相同 15s 素材,1440p

时间线帧率 慢放倍数 时间
120fps 0.2 1 : 42
240fps 0.4 1 : 38
240fps 0.25 2 : 55

120fps 与 240fps 导出时间的误差可以忽略不计

Blur 设置

output timescale 根据你原素材慢放倍数进行调整

注意需要一条没有变速的素材的音频轨道

动态模糊渲染对比

左 960 -> 60,右 600 -> 60

渲染效果 Render Test #7 ( Recorded by Rewind ) - Revethere

其它功能

自己摸索摸索吧,这次更新的这个 mod 真的挺好 $\phantom{其实是懒(}$

甚至能做绿幕❗

MORE

『sumo 打法教学 & 浅层理论分析 & 心理博弈』

教程 2025/8/7

阅读文章前,你需要知道的…

  • 文章中所有的定义(以及一些生僻概念)仅为了规范与统一文章的内容,不代表圈内叫法👌🏼

  • 文章中所有涉及的操作均通过 dbc 点击方式实现,同时您也需要熟练使用间隔点

  • 大部分技巧讲简述原理,少数从底层机制分析

  • 部分技巧因适用于多个场景会重复出现

  • 为了方便表示,大部分 click 都用单数

  • 原本想试试图文的但是图片太难做了,受限于样式这种做视频其实会好点

本文内容仅代表个人观点❗❗❗

Early Game - 基本技巧原理简述 & 部分技巧的细分与重定义

基本技巧

  • wtap / 重置疾跑

    严格意义上是两个技巧,但在这里不作区别

    需注意一点:wtap 可以增大对方的 kb 同时自己的 kb 也会增大,不要一味地叠 wtap,根据情况 hold w 也可以获得非常优秀的 kb

  • stap

    分为 s-tap 和 ws-tap,s-tap 是松开 w 按 s(会有较明显的后退),ws-tap 则是 hold w 并 tap s(有点类似急停)

    s-tap 适用于完全预判对手 hitselect,ws-tap 则相对保守,更多见『End Game』章节

    据说打的时候下落阶段按 s 可以更快下落但是我真没研究明白(按理来说不应该啊

    staper 是真重,也是真稳

  • hitselect ( hs )

    分为 light hs 和 hard hs,在这里将 light hs 定义为玩家收到上升 kb 的时间内(大约达到最大高度的 60% ~ 80%)进行 hs,hard hs 则是在上述时间之后到下次受到击退前

    建议在距离 3.5blocks 的时候开始点击,你的 kb 会在攻击被注册之前受到,wtap 的节奏会好把控一点

    先手也没关系,只要对方不是长后手第二下 trade 回来就没问题

    hard hs 一般称为长后手,更适合打一个出其不意

  • midtrade ( mt )

    典中典啊,可以说这个技巧是 sumo 的必修课

    在这里定义玩家进行 midtrade 时上次结束到下次攻击被注册为一个 trade

    同样分为 light mt 和 hard mt,对于时机的区别与上述 hs 的相同。light mt 对于较依赖 wtap 节奏的玩家作用不言而喻,hard mt 的作用则与 hard hs 相似

    掌握 midtrade 需大量练习,难以言传,多打即可 o.O

    关于 mt 时机及更多 mt 相关技巧详见『Early Game』- 『衍生技巧』与『End Game』-『mt 节奏』章节

  • jumpreset ( jr )

    虽然这是作为萌新相较于 wtap 更先听说的技巧,但对于我来说 jr 更贴近被动技巧。一般是用来脱离 combo,或是拥有良好 timing 把控在 mt 被创飞的一瞬间 jr 重置 kb 继续对刀(被创飞的第一刀落地再 tap space会有较高的成功率)

    当然也有将其作为主要技巧的且打得也非常厉害的玩家,至少我不行(

    相关 jr 重置 kb 实例(主要是水平 kb)计算如下:

    $\phantom{找不到数据,Wiki 上的东西太杂了,绝对不是我懒(确信}$

    $\phantom{后面如果补这部分的话应该会新开一篇}$

    ⬆空白?打开 F12 看 awa

  • run

    是的,就是当 runner。

    不过也需要注意一下与台边的距离别逃的时候掉了

    建议是在与台边比较远的时候被 combo 再逃,一般距离还是 jr 算了

  • strafe

    很多 sumo 玩家往往专注与去拼体重而忘记了走位发挥的作用。除了偏移击退以外,还可以干扰瞄准减少对方注册的点击

    一般建议在距离对方 3.5blocks 的时候走位或是贴近后在自己受到击退前开始走位

衍生技巧(后续应该会补很多)

  • 负 kb

    仅仅依靠间隔点实现的极小 kb + 间隔期间前进的位移实现的负 kb

    一般适用于对方 wtap 频率不高,同样对于 lowping 的 sumo 对局(50ms 以下)一直卡 3blocks 的对刀有一定的效果

  • mt 偏移

    指在玩家之间相互 midtrade 的间隙通过走位干扰对方瞄准并在下次攻击时改变对方击退方向,一般是在本次攻击之后玩家之间距离拉近或是穿身时使用(这个就需要多打打判断了)

  • release w

    这个技巧归类到心里博弈会好点,这里单独提出来,会累赘一点但是问题不大。

    在玩家之间相互 midtrade 时判断本次攻击之后会穿身因此在本次攻击时松开 w 并在对方的攻击注册时重新按下 w 并攻击(在平台边缘并且处于优势位置效果最佳,毕竟要是没处理好穿身后自己就被创下去了)

    一般对方会以为穿身往后瞄准(但事实上并没有)被创下台或者进入 combo,另一种就是避免自己进入劣势局面

  • midtrade 反制(mt cm)

    不会。

    会了再补 o.O

    其实也不算完全会

    反制手段要么就是 trade 回去,相互保持 trade(对于不会直接创下台的情况);或者是 spam click(trade 节奏较长的时候)

    都是等对面失误

    那什么高低位,不懂(

  • air jump

    非常猎奇的我觉得应该不能称之为技巧的技巧,我一般对其解释为在服务端玩家被判定为 onGround 但在客户端玩家视角是在空中进行跳跃重置。非常有用,但是很吃 timing(似乎 1.8 更容易触发?)

    mmc 这个赛季(Season 9) air jump 触发的手感挺奇怪的,tap space 到触发 air jump 之间有延迟而且成功概率挺大,感觉 combo 时只要 3combos 没问题基本对面逃不了

  • backtrack

    此 backtrack 非彼此 backtrack,其实就是 misplace 刀

    当你和对手的 ping 处于一个暧昧的关系时,你 / 对手会莫名其妙在推开之后老远再摸到一刀(具体怎么触发不知道)

    总之当你能触发就能恶心对面,对面触发容易被打红温(

    而且一旦能够触发那大概率一长段时间内都能恶心对面(

    奇妙😱

关于 dbc 间隔点

在这里将两指分别敲击一次鼠标(一般为 4cps)的操作称为 1tc;一般地,8cps 间隔点简称为 2tc,12cps 为 3tc

这只是一种叫法,与有没有触发双倍点无关

如果能够做到在短时间内的 4tc 点击,那你的 kb 将会进化到下一个等级

2tc 和 3tc 的点击建议放长一点,不然点击之间间隙太大容易创飞

一些奇妙的想法

  • 忘记从哪看的聊天记录了简单来说就是在 1gt 内你的点击无限接近于 12cps 并且不超过这个值(还是 13cps 来着我忘了),能够触发 double hit

    真实性待考证,仅基于不可靠理论推测

  • (不太合法的)减 kb 的新思路

    在解释这个思路之前,补充一点理论:

    1. Minecraft 中所有可运动实体都有一个 motion 的属性,这个属性可以认为是一个存储速度及运算其中间量和一个三维向量的容器;速度属性被表示为在一段时间内表示坐标值变化量的三维向量。但是此处不对这两个概念进行区分,后文不管是用 motion 还是速度可以相互转换

    2. 三个非常重要的公式

      $\frac{dv}{dt} = a - fv$

      $\frac{v}{v_0} = \lim\limits_{t_0 \to 0} (1 - f t_0)^{\frac{t}{t_0}}, a = 0$

      $v = v_0 e^{-ft} + \frac{a}{f} (1 - e^{-ft})$

      其中 $f$ 是阻力系数(这里仅考虑空气阻力和点击受到的减速效果的阻力,这里称为点击阻力),$t_0 = 1 gt$

      虽然都很重要但最重要的是公式三,其描述了物体从初始到任意的整个时间 $t$ 内,速度的完整变化过程。但最重点的不是这个😶‍🌫️

      最最重要但很显然的是,在 Minecraft 中这一设定无法精准实现,Minecraft 中最小的时间单位是 1gt,$dt$ 和 $t_0$ 显然无法小于 1gt。游戏中对于这一运算的实现简单来讲则是通过将受阻力的各轴对应的 motion 减去对应轴上以 $gt^{-1}$ 为单位的阻力系数的乘积;从物理上来说,实体在 $t_0$ 内的 motion 可以看作一个平均值 M,那么 motion 与阻力系数的乘积可视为其在 $t_0$ 时间内的冲量,即:

      $M_{作用后} = M_{作用前} - f t_0 M_{作用前} = (1 - f t_0)M_{作用前}$

      其中 $(1 - f t_0)$ 在这里称为速度乘数,记作 $k$。也就是说,实体受到阻力的本质就是 motion 乘以了这个数。这也就是为什么你刷到的有些减 kb 的分析很多是说速度乘以 0.6❗

    接下来该进入正题了

    这里暂且不考虑击退刻的问题,假设玩家的 1s 内一直都受到击退(当然实际情况不是这样)

    对于分布均匀的 dbc 20cps,放到时间轴上大概长这样(左键可放大):

    玩家的 double click 每次只落在了一个 gt 上

    其 motion 受到阻力作用的时间(只考虑点击阻力)只有 10gt

    如果将点击偏移一下(大概半个 gt 左右):

    double click 的第一下落在上一 gt 末,第二下落在下一 gt 的开始,两次 click 分别落在了两个 gt 上。这样玩家在 1s(20gt)内都能受到阻力的作用

    恭喜你成为了胖子🥳

    当然在现实中你的点击肯定不会这么均匀

    真实的点击大概长这样:

    注意到 16cps 时受到阻力作用的时间只有 8gt(情况好点可以到 9gt)

    20cps 基本可以稳定 10gt(同样,情况好点能到 11gt 或更多)

    24cps(在上述片段中)阻力作用时间为 13gt(实际情况下应该是在 12gt 到 14gt 之间)

    显然,16cps 的体重与 24cps 的体重完全不在一个水平线上

    但我们讨论的重点不在这里

    是否可以写一个 mod,在客户端接收到 double click 时候,自动将点击修正到两个 2gt 之间?

    虽然说 Minecraft 每秒只有 20gt,也就是说我们的修正操作只能按 gt 进行。但是我们完全可以判断当前 gt 是否存在 double click,若存在则将 double click 的第二下在下一 gt 开始的时候发包出去(我这里写的可能不是很清楚,我没做过 mod,客户端与服务端之间的通信了解的也不多,这里只是提供一个思路,不保证完全可以实现

    修正后的点击:

    但是修正后点击太均匀可能会触发 ac 检测(随机触发就好了)

    注意在模拟的 24cps 点击图中第 6gt 末的点击是在第 7gt 才触发。最后一个 gt 中较后的点击将会移到下一秒(即在点击之后处理)

    逻辑有点乱,大概思路是这样

Mid Game - 从长久计的打法习惯养

关于默认打法

毫无疑问有一个默认打法然后基于此打法进行衍生是极其重要的(听君一席话,如听一席话😶‍🌫️

建议你的默认打法满足以下几点:

  1. 尽可能地简洁
  2. 对于第一刀有针对性优化(不管先后手都能保证一定的优势)
  3. 适合长时间 q(点击优化)

比如我现在的默认打法就是接近时(大于 3blocks)开始点击(3tc),如果是先手第二下 mt,之后的对刀 wtap + 2tc / 3tc(根据情况交替)

当然这只是一个参考,第一刀同样可以 wstap 进行试探再根据对手打法调整

特定场景下的打法优化 & 实例分析(或许会有图文)

阅前提醒:对于「特定场景」显然无法全覆盖,所以在这里仅举例一些(或许算是)典型的场景(慢慢填)

  • 在默认打法下,对方比自己重(kb 相对较小),且无其它转换先后手的技巧(或此类技巧极少)

    增加间隔点频率,尽可能多的 3tc 点击,在保证自己 kb 不会乱飘的同时适当增加 3tc 点击密度(尽量保持 3tc 本身的点击次数)

    根据距离选择性 wtap,离得近就 wtap 增加对方受到的 kb,反之亦然

  • 对手打法上总体偏向后手,先手刀较少

    尝试比对面更长的后手(出其不意的后手),预判后手穿身或者 release w + hs。在 kb 上势均力敌那就抓推开后第一刀的失误

    面对这类玩家第一刀十分重要

  • 对手点击间隙较短(或大部分是 spam click),不要尝试放长 hs 或是长 mt,因为在第三刀后你大概率会莫名其妙空刀然后被推飞

    慢节奏的 3tc 或 4tc 的点击去拼 kb 就行,spam click 的体重一般是拼不过间隔点的

  • 面对 lowping 的对手一定要 first hit + spam click,不然那距离太抽象了

  • 如果对方开局就是 wa 或者 wd 那大概率是短后手,wstap + spam click 基本可以保证开局不被推飞,并且能够在接近 3blocks 的距离下有较好的先后手转换容错

    如果对方是接近时 strafe 那就顺着对方的方向按 a / d,预判错了页面也没关系,spam click 可以保证第二下不会推太远

  • 如果感觉对面的 kb 突然变小或是垂直 kb 突然变高那大概可以推断对方 jr,可以尝试放短 mt

  • 对方特别重并且 holdw 能够获得负 kb,可以 wtap 硬推或者对刀按 ad 飘对面

  • 关于 mt 技巧的推测见下一 part 『End Game』-『mt 节奏』

一些畸形打法

  • only hs

    几乎每一刀都是 hs,这对于稍微有些经验的对手很容易识别并 stap 反制

  • 预判型 jr

    此处指的是将 jr 作为主要技巧并且预判 jr 的占比比较大的玩家

    mt 预判失败直接就飞了

  • pinger ( over 130ms )

    在有加速 ip 或者加速器的情况下请不要用高 ping 玩❗❗❗虽然高延迟玩的少但是据我了解第一刀打法主要就是侧身 + 长 hs 很容易反制,同时这样的 ping 在对刀中节奏非常不好把控

    130ms 左右的延迟都还算可以接受(比如 boxing 圈有 BBDL 这样非常强势的 130ms 玩家),再高真的不行了

    其实 90ms 以上的延迟打起来就已经很难受了

    更多关于延迟的讲解见下一部分『关于延迟』

  • trader

    对刀严重依赖 mt,具体表现为每一刀的攻击节奏慢于正常节奏 $\phantom{比如某个lowA Tier}$

    很难说这个习惯是好是坏,trade 节奏不好很容易失误(但是又很难定义「不好的 trade 节奏」,大概就是你和对面相互 trade 但是先后手基本没变或是同时,然后你 spam click 不再 trade 拼几刀后对面会被推走,对面就是「不好的 trade 节奏」)

    瞄准不好的话被对面 mt 偏移直接被创飞

关于延迟

不想写了,有空再填这个坑(🤐

The ULTIMATE Guide to PING - sceyna

现在好讨厌打 lowping 的对局,尤其是在 wihar,小的 kb 拼不过,技巧在 lowping 的作用很小😕 $\phantom{kb 还很猎奇}$

但是 wihar 新赛季(Season 4)的水平 kb 好像变小了,可以直接推了(

End Game - 心理博弈

如何心平气和地打 ranked sumo

众所周知 ranked sumo 是 ft3,因此在第一局中判断对手打法以及在比分 2 : 2 时稳定心态十分重要

如何心平气和地打 ranked sumo如何快速破防红温💀:

  • 被黑客飘

  • 被疯狂打出 misplace 刀

  • 遇上 elo 核弹被吃满 elo

  • 开局预判对手先后手失败直接创飞,0 : 1(微红❗

    开局预判对手先后手失败直接创飞,2 : 2(破防❗❗

    开局预判对手先后手失败直接创飞,2 : 3(虾波❗❗❗

    🤬🤬🤬

但是说真的,ranked 打多了还真不太容易被整红温😗

建议整个不在意数据的小号打打

嗯很好地水了一小章

mt 节奏

根据对手的习惯一般分为两类 trade 节奏:持续性 trade 和反 trade

  • 持续性 trade 节奏

    双方保持相互 trade,即很少情况 spam click 转变对刀节奏

    经典的反制手段是在三次 trade 后 spam click 加快对刀节奏,对手点击间隔长的话会直接被创飞(更多时候需要根据 trade 间隔时间判断)

    另一种是叠 4tc 点击拼体重(对于体重较重的)

  • 反 trade 节奏

    本质上是对手为了转变先后手而进行 mt,可以理解为间歇性 mt

    要么就是你 trade 一下我 trade 一下看谁先失误

    要么就让着对面后手拼体重

    最好的办法是推开之后抓第一刀失误

其它博弈

待补

其它

观赏性 sumo

在高手玩家对局中想要得到以下两类观赏性的 sumo clip 几乎不可能(偏向于技巧上的观赏,但是对于圈外显然无法 get 到其观赏性),所以更多会是演员或者有点技术但不多的小趴菜 o.O

不保证说法完全正确,大概意思没问题就行(

  • circle combo ( + style )

    关于环绕 combo,国外有非常高质的创作者,见 iusehuzuni 的频道(这家伙一年没更新了www~)

    combo style 则是在环绕 combo 的过程中进行 style,大致可以理解为 boxing style,但相比于 boxing style,sumo 的 style 对瞄准、控距要求更高,节奏也与 boxing 差异很大

  • hitting style

    在对刀中的 style,对瞄准及注册到的点击要求较高(此处注册到的点击指的是你的 hits 注册到实体的数量),需要对方较低的 wtap 率和几乎没有的技巧

    特别适合跟那些没脑子的 ac 晃悠

建议在尝试观赏性 sumo 之前,多打打 boxing,当你的 boxing style 观赏性足够高的时候 sumo 的观赏性也不会差🥰

国内目前几乎没有观赏性较高的 sumo 玩家,尤其是 hitting style。嗯对除了我 QAQ

部分圈内玩家打法分析(不代表最新)

原本是想把这个放到打法优化那个 part 写的,在这里单独列出来

很久以后再补吧 QAQ

一些奇妙的东西

HitDelayFixMod

MouseDelayFix

参考资料

Minecraft 实体运动研究与应用 - lovexyn0827

The only Minecraft sumo guide you’ll ever need - crracky

How Minecraft PvP really works - luzis

The ULTIMATE Guide to PING - sceyna

更新日志

25.10.6 -(主体)完结撒花🥰🥳🎉

MORE

『录制 & 渲染配置分享(OBS & Blur)』

配置 2025/7/30

超级省流版:

编码器配置文件

Blur 渲染配置文件

OBS 设置

常规设置

录制设置

编码器设置

一些录制建议

分辨率一般建议缩放为 1080p,略微提高分辨率后期做视频的容错更高,酌情选择

录制帧数 120fps 在进行渲染后基本够用,B 站压缩后与 240fps 的渲染差别应该不大

如果你的内存足够用的话选择 H.264 编码器也无妨。

  • 240fps、1080p 的录制规格下 H.264 的视频码率大约在 100mbps 左右?

  • 240fps、2k 的录制规格下 H.265 编码的视频码率大约在 45mbps 左右,以此类推

目标质量设为 16 为视觉无损,大部分情况也够用,更高的质量带来的视频观感的提升并不明显

Blur 设置

软件下载

Config

一些渲染建议 & 错误处理

blur-weighting 建议选择 vegas(目前观感最好)

插针倍数(interpolated fps)不建议超过 6x,建议使用 svp 而不是 rife 模式进行插针(否则您将会体验到非常慢的速度以及报错的视频)

AI 补帧(pre-interpolation)视个人喜好而定,开启画面会有一种粘腻感。倍数越高,渲染速度越慢

质量(quality)拉到 16 差不多就够了,似乎是因为软件没有进行多次编码导致输出文件过于庞大(如果您不在意内存消耗可以掠过)

如果你遇到了与该 issues 相同的问题,尝试关闭 GPU 编码,如果还是不行,请重置渲染设置

更多详见 README

MORE

『奇淫巧技之最强 C++ 封装快读快写模板』

竞赛 2025/7/26

源码见 Github

或直接在以下代码块中直接复制:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <new>
#include <type_traits>

namespace BetterIO {
    namespace ExtraType {
        inline bool isDigit(const char &ch) {
            return '0' <= ch && ch <= '9';
        }
        inline bool isLetter(const char &ch) {
            return 'A' <= ch && ch <= 'Z'
                || 'a' <= ch && ch <= 'z';
        }
        inline bool isChar(const char &ch) {
            return isDigit(ch) || isLetter(ch);
        }
        inline bool isVaild(const char &ch) {
            return '!' <= ch && ch <= '~';
        }
    }
    using std::string, std::is_same_v;
#ifndef BUFFER_SIZE
#define BUFFER_SIZE 1 << 16
#endif
    class betterInput {
        FILE *stream;
        char *buffer, *iter;
        int buffer_size, volume;
        void input() {
            volume = fread(buffer, 1, buffer_size, stream);
            iter = buffer;
        }
        inline void getChar(void) {
            if(iter - buffer == volume) input();
            else ++iter;
        }
    public:
        betterInput(FILE *stream = stdin) {
            this -> stream = stream;
            buffer_size = BUFFER_SIZE;
            buffer = new char [buffer_size];
            iter = buffer;
            volume = 0;
        }
        template <typename _Tp> betterInput& operator >> (_Tp &var) {
            if constexpr(is_same_v<_Tp, char> || is_same_v<_Tp, string>) return inputCharType(var);
            else {
                static bool neg = false;
                while(!ExtraType::isDigit(*iter)) {
                    neg ^= *iter == '-';
                    getChar();
                }
                var = 0;
                if constexpr(is_same_v<_Tp, float> || is_same_v<_Tp, double>) return inputFloat(var, neg);
                else {
                    while(ExtraType::isDigit(*iter)) {
                        var = (var << 1) + (var << 3) + (*iter ^ '0');
                        getChar();
                    }
                    if(neg) var = ~var + 1;
                }
            }
            return *this;
        }
        template <typename _Tp> betterInput& inputCharType(_Tp &var) {
            while(!ExtraType::isVaild(*iter)) getChar();
            if constexpr(is_same_v<_Tp, char>) var = *iter, getChar();
            else {
                var.clear();
                while(ExtraType::isVaild(*iter)) {
                    var.push_back(*iter);
                    getChar();
                }
            }
            return *this;
        }
        template <typename _Tp> betterInput& inputFloat(_Tp &var, const bool &neg) {
            while(ExtraType::isDigit(*iter)) {
                var = var * 10 + (*iter ^ '0');
                getChar();
            }
            if(*iter == '.') {
                getChar(); 
                _Tp dec = 0.1;
                while(ExtraType::isDigit(*iter)) {
                    var += dec * (*iter ^ '0');
                    dec /= 10;
                    getChar();
                }
            } else getChar();
            if(neg) var = -var;
            return *this;
        }
        ~betterInput() { delete[] buffer; }
    };
    class betterOutput {
        FILE *stream;
        char *buffer;
        int buffer_size, volume;
        inline void putChar(const char &ch) {
            if(buffer_size == volume) flush();
            buffer[volume++] = ch;
        }
    public:
        betterOutput(FILE *stream = stdout) {
            this -> stream = stream;
            buffer_size = BUFFER_SIZE;
            buffer = new char [buffer_size];
            volume = 0;
        }
        void flush(void) {
            fwrite(buffer, 1, volume, stream);
            volume = 0;
        }
        template <typename _Tp> betterOutput& operator << (_Tp var) {
            if(var < 0) putChar('-'), var = -var;
            if constexpr(is_same_v<_Tp, float> || is_same_v<_Tp, double>) return outputFloat(var);
            else {
                static char digit[25];
                static short cur = 0;
                do digit[cur++] = static_cast<char> (var % 10 + '0'); while(var /= 10);
                while(cur) putChar(digit[--cur]);
            }
            return *this;
        }
        betterOutput& operator << (const char &var) {
            putChar(var);
            return *this;
        }
        betterOutput& operator << (const char *var) {
            while(*var) putChar(*var++);
            return *this;
        }
        betterOutput& operator << (const string &var) {
            for(auto cur: var) putChar(cur);
            return *this;
        }
        template <typename _Tp> betterOutput& outputFloat(_Tp &var) {
            const string str_var = std::to_string(var);
            for(auto cur: str_var) putChar(cur);
            return *this;
        }
        ~betterOutput() { flush(); delete[] buffer; }
    };
#undef BUFFER_SIZE
}

signed main() {

    return 0;
}

模板简介

为了更好地食用模板,请务必仔细阅读以下内容

  • 完整版代码长度4.7k,不考虑写成头文件(毕竟竞赛没有多文件)。或者也可以选择 Lite 版 模板

  • 使用 fread/fwrite 函数实现。默认缓冲区大小为 $2^{16}$,也可以通过更改模板中 BUFFER_SIZE 的值来更改缓冲区大小(不建议超过 $2^{23}$)

  • 重载了 >><<,可以像使用 cin/cout 的方式来进行读写

  • 不要与相应的输入输出流混合使用(比如同时使用 freadcinfwritecout),fread/fwrite是一次性从缓存中读取 / 输出数据,混合使用会导致变量数据错误等无法解决的问题

    支持 Linux 和 Windows 环境,如果可能会尝试写一个 mmap 版本(Windows下通过 CreateFileMapping 实现)

  • 经调试应该没有什么大的问题,如果有的话可以 Luogu 私信我,会尽快修改

    请保证您传入的参数是合法的,出现任何未知的问题概不负责

功能介绍

  • 若要使用此模板,请通过 BetterIO::betterInput inBetterIO::betterOutput out 来创建对象

  • 支持整形、字符、字符串、浮点数的输入,整形、字符、字符串、浮点数、char* 的输出(在现在的竞赛环境下几乎不会用到 char* 类型的输入,故舍弃)

    关于 bool 类型的数据,对其单独写一个输入 / 输出函数是没有任何意义的,故舍弃

  • 您可以使用 in >> x; 读入一个以上任意的一个类型的数据,使用 in >> x >> y >> z >> ...; 读入任意个以上支持的数据类型

  • 对于 charstd::string 类型的输入,默认有效字符的范围为 ACSII 码表中的 33 至 126

    您可以通过更改以上输入类型的判定条件输入特定字符范围的数据

    ...
    template <typename _Tp> betterInput& inputCharType(_Tp &var) {
        while(!ExtraType::isVaild(*iter)) getChar(); // 更改 ExtraType::isVaild 函数以输入特定字符范围数据
            if constexpr(is_same_v<_Tp, char>) var = *iter, getChar();
    ...
    
  • 命令行输入完数据后,使用 ctrl + z 刷新缓冲读入数据。文件流无需注意此项

  • 您可以使用 out << x; 输出一个以上任意的一个类型的数据,使用 out << x << ' ' << y << ' ' << z ...; 输出任意个以上支持的数据类型(带空格)

  • 对于浮点类型的数据(floatdouble),默认输出精度为 6 位小数,不支持更改精度绝不是我太懒了懒得写

    若有其它精度输出的需求请用其它输出方式

性能比较

待补 —— 25.7.26

MORE
1
avatar
Revethere₂₀₂₄

INTP-A
好想谈恋爱 😳