团队周报007期:优雅的暴力

news/2025/2/1 11:37:47/文章来源:https://www.cnblogs.com/Kenma/p/18696221

前言

感谢 mkr 同学积极和我协商沟通,使我更了解大家的情况。

考虑到很多高级算法难度过大,并且以后大家也会逐渐接触,所以这些东西我就不写了。

本篇文章从一个特殊的角度切入,着重介绍一类着有相同思想的题目,希望大家感受到这股劲。

虽然我读的博客也不多,但是我没有见过和本篇文章相似的博客(骄傲)。

文章配套题单也迁移到了团队题单中。

正文

你有没有见过这样一类题目,你很快想到一个复杂度比较劣的做法,却怎么也想不出正解。

大战两小时拼尽全力无法战胜后,你打开了题解:

按题意模拟即可,复杂度为 \(O(n \sqrt{n})\)

或者是:

不难发现直接做就是对的。

甚至是:

用脚维护,不需要脑子,我写了。

你发现最开始你想的做法是正确的,只不过需要一点小小的改变。可能是改变枚举顺序,可能是加上一点小小的剪枝,可能是记忆化。甚至有可能你尝试实现了你的想法,以为会 T 飞,但是实际上跑的飞快,直接草过。

此时有一个 OIer 轻轻地碎掉了。

在你的意识逐渐模糊之前,你的脑子里只剩下一句话:

这类题到底应该怎么思考?

看小说看多了导致的。

这类题一般被称为暴力题。

对暴力题做一些更准确的描述:暴力题正解的复杂度看起来很高,但是经过精细分析与惊喜实现后,复杂度很优秀,是可以通过的。

  • 如果你见过暴力题,并且苦于这类题应该怎样入手思考,那么恭喜你,这篇文章正是你想要的;

  • 如果你没有见过暴力题,那么也恭喜你,今天你能看到六道暴力题,感受做(chi)题(shi)的快乐;

  • 如果你觉得题目有点简单,那么也恭喜你,有了一个装逼的机会。请私信嘲讽我,我会添加一些更加困难的题目,并膜拜您因为您太强了。

反正恭喜你.jpg

在我学 OI 的经历中,暴力题一般和思维题放在一起讲,暴力题的做法实际上是思维难度高,实现难度低的做法。

但是我觉得有必要把这类题单独摘出来说,让大家充分感受暴力美学。

今天我找来了六道有代表性的暴力题,题目难度按我主观感受难度排序。

因为所有题的思维难度和实现难度都不高,所以建议有精力的话都要好好思考理解。

和上一篇周报不一样,因为这类题的思考方式都比较相似,所以这次不再设置提示。

同样地,在看做法之前,应该先独立思考,如果有很好的想法的话可以写完直接交,万一过了呢。

让我们开始吧!

例题一

[JRKSJ R6] Eltaw

有无音游老哥给大家弹一首 Eltaw。

按题意模拟即可。

具体地,对于每次询问 \(l,r\),如果 \(l,r\) 在之前询问过,那么直接回答询问。否则,暴力枚举 \(k\) 个序列,用前缀和求出区间和,取最大值。

可以证明复杂度不超过 \(O(\max(q,nk) \sqrt{nk})\),可以通过本题。

考虑证明:

  • \(n \le \sqrt{nk}\),即 \(n \le k\) 时,因为至多有 \(O(n^2)\) 种不同的 \((l,r)\),对于每一组 \((l,r)\),都需要 \(O(k)\) 的复杂度来求出答案,总体复杂度为 \(O(n^2k)\),即 \(O(nk \sqrt{nk})\)

  • \(n > \sqrt{nk}\),即 \(n > k\) 时,因为至多有 \(q\) 次询问,每次询问复杂度为 \(O(k)\),总体复杂度为 \(O(qk)\),即 \(O(q \sqrt{nk})\)

综上,复杂度不超过 \(O(\max(q,nk) \sqrt{nk})\)

#include <bits/stdc++.h>
using namespace std;
int n, k, q;
const int N = 5e5 + 5;
int *a[N];
long long *s[N];
long long ans[705][705];
inline int read() {int x = 0;char ch = getchar();while (!isdigit(ch)) ch = getchar();while (isdigit(ch)) x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar();return x;
}
int main() {ios::sync_with_stdio(false);cout.tie(NULL);n = read(), k = read(), q = read();for (int i = 1; i <= k; i++) {a[i] = (int*)calloc(n + 1, sizeof(int));for (int j = 1; j <= n; j++)a[i][j] = read();}for (int i = 1; i <= k; i++) {s[i] = (long long*)calloc(n + 1, sizeof(long long));for (int j = 1; j <= n; j++) s[i][j] = s[i][j - 1] + a[i][j];}if (n <= sqrt(n * k)) {memset(ans, ~0x7f, sizeof ans);for (int i = 1; i <= k; i++) {for (int j = 1; j <= n; j++)for (int l = j; l <= n; l++) {ans[j][l] = max(ans[j][l], s[i][l] - s[i][j - 1]);}}for (int i = 1; i <= q; i++) {int l = read(), r = read();cout << ans[l][r] << '\n';}} else {for (int i = 1; i <= q; i++) {int l = read(), r = read();long long res = -1;for (int j = 1; j <= k; j++)res = max(res, s[j][r] - s[j][l - 1]);cout << res << '\n';}}return 0;
}

例题二

如果你想直接上线段树维护取模那么建议重学线段树。

推销我在 S2OJ 上写的题解:here.

难受的是,取模运算没有交换律也没有结合律,也就意味着用什么数据结构维护区间取模都是妄想。

但是,取模有一个很有意思的性质:在经过取模运算之后,被模数只会越来越小,并且如果被模数改变,那么被模数至少减少至原来的一半

此时的你:草这不是做完了吗。

具体地,每次在区间 \([l,r]\) 中寻找最小的 \(i\),使得 \(x \ge a_i\),令 \(x \to x \bmod g_i\),直到区间里的都 \(>x\) 为止。

每次寻找 \(i\) 可以用 ST 表加二分实现,也可以用线段树上二分实现,甚至可以用文艺平衡树做,复杂度都是 \(O(\log n)\),相信大家都会。

根据上面的结论,每次取模都会使 %x% 减半,那么取模的总次数不会超过 \(\log x\)

所以,总体复杂度为 \(O(n \log n \log x)\)

我写的是线段树上二分,但是考虑到很多人不会,所以我把别人的 ST 表加二分贺过来了。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+100;inline int read()
{int x = 0, f = 1; char ch = getchar();while(ch<'0'||ch>'9'){if(ch == '-') f = -1;ch = getchar();}while(ch>='0'&&ch<='9'){x = x*10+ch-48; ch = getchar();}return x*f;
}
int lg[N];int a[N], n, m;
int st[30][N];
void prelg(){for(int i = 2; i<=n; i++) lg[i] = lg[i>>1]+1;
}
void add(int pos)
{st[0][pos] = pos;for(int i = 1; i<=lg[pos]; i++){if(a[st[i-1][pos]]>a[st[i-1][pos-(1<<(i-1))]]){st[i][pos] = st[i-1][pos-(1<<(i-1))];}else{st[i][pos] = st[i-1][pos];}}//这里使用st表存最小值位置,写的真滴丑qwq//貌似存值也可以,本蒟蒻想多了xwx
} int query(int l, int r)
{int lth = r-l+1;if(a[st[lg[lth]][l+(1<<lg[lth])-1]]>a[st[lg[lth]][r]]) return st[lg[lth]][r];else return st[lg[lth]][l+(1<<lg[lth])-1];
}
int find(int lq,int rq,  int tar)
{int ans = rq+1, ln = lq, rn = rq;//未找到则返回rq+1while(ln<=rn){int mid = (ln+rn)>>1;if(a[query(ln, mid)]<=tar){rn = mid-1;ans = mid;}else{ln = mid+1;}}return ans;
}
int main()
{n = read(), m = read();prelg();for(int i = 1; i<=n ;i++){a[i] = read();add(i); }while(m--){int x = read(), l = read(), r = read(); while(l<=r){l = find(l, r, x);if(l>r) break;else x%=a[l];}printf("%d\n", x);}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Qwen2.5-VL:更强大的多模态大模型|附实测结果

模型更新简述 几天前,通义千问更新了最新的多模态大模型Qwen2.5-VL,拥有包含 3B、7B 和 72B 在内的 3 个模型尺寸,同时完全开源,可在huggingface和modelscope下载到所有模型权重。 1. 更灵活的时空维度处理 ● 空间维度上,动态地将不同尺寸的图像转换为不同长度的token,并…

第五节上,图像分类实战,食物分类

随机种子固定随机结果,方便复现 def seed_everything(seed):torch.manual_seed(seed)torch.cuda.manual_seed(seed)torch.cuda.manual_seed_all(seed)torch.backends.cudnn.benchmark = Falsetorch.backends.cudnn.deterministic = Truerandom.seed(seed)np.random.seed(seed)o…

对比使用DeepSeek与文新一言,了解DeepSeek的关键技术论文

DeepSeek是国内大模型技术的新秀,最近也在业界和媒体界火爆出圈,所以想学习一下其技术。 大模型时代,学习知识,当然首先想到利用大模型,由于在过去一年,对DeepSeek使用不多,所以想和文新一言(4.0 Turbo)对比使用。 通过对比,针对同一个问题“DeepSeek发扬开源文化,将…

Cisco NX-OS Software Release 10.5(2)F - 网络操作系统软件

Cisco NX-OS Software Release 10.5(2)F - 网络操作系统软件Cisco NX-OS Software Release 10.5(2)F - 网络操作系统软件 NX-OS 网络操作系统 请访问原文链接:https://sysin.org/blog/cisco-nx-os-10/ 查看最新版。原创作品,转载请保留出处。 作者主页:sysin.orgCisco NX-OS…

pdf处理--tts(待重写)

1.提取正文2.裁剪页眉 https://smallpdf.com/cn/crop-pdf#r=crop-pages3.拆分4.ocr 效果图--白描:效果图--4Videosoft PDF Converter Ultimate:5.阅读器与tts引擎 开源阅读:https://github.com/gedoor/legado tts-server-android:https://github.com/jing332/tts-server-an…

INFINI Labs 产品更新 | Console 发布 TopN 功能,Easysearch 新增 Rollup 能力等

INFINI Labs 产品全新发布!此次更新为大家带来了 Console 的全新 TopN 功能,让您能够更高效地定位最关键的节点或索引;Easysearch 新增 Rollup 能力,大幅提升监控指标的存储周期并优化分析体验;此外,Framework 还修复了多项缺陷并进行了多处优化。欢迎下载体验,探索更多…

03-一个例子

登录被测系统bysms双击运行runserver.bat 访问页面:http://127.0.0.1/mgr/sign.html 账号:byhy,密码:88888888 可以直接在pycharm的Terminal中运行hytest,不需要打开命令行窗口 浏览器驱动的打印信息: 禁止 chromedriver 日志写屏1 from selenium import webdriver 2 3 …

blog tips

markdown 内嵌 html 使图片并排点击查看代码 <div style="display: flex; gap: 10px; justify-content: space-between;"><img src="图片1地址" style="width: 49%; height: auto;"/><img src="图片2地址" style="…

【数学】已知正方形相邻两点坐标求另外两点坐标

已知正方形相邻两点(a,b)与(c,d)坐标公式: \( (x_3,y_3) = (c + (b-d), d - (a-c)) \\ (x_4,y_4) = (a + (b-d), b - (a-c)) \\ (x_5,y_5) = (a - (b-d), b + (a-c)) \\ (x_6,y_6) = (c - (b-d), d + (a-c)) \)

25.1.31小记

多态类型声明类型 : 定义时候的类型 动态类型 : 运行到那里的时候对应的具体类型 向上造型(cast) : 将子类类型的对象赋给父类的变量 (不能将一个父类的变量赋予一个子类的变量) 赋值运算符 : 将管理者管理的对象进行改变(改变的是指针)其中造型(cast)的意义是将某…

MacOS修改应用快捷键的一般思路

具体步骤为:使用CheatSheet软件查看菜单项名称 在系统设置中修改菜单项的快捷键举个例子:修改Chrome中左右切换tab的快捷键(系统语言为英文,中文同理) 默认采用Ccontrol Tab和Control + Shift + Tab(或Command Shift [和Command Shift ])可以左右切换tab。 现在希望将其…

UE4.27, 模块实践, Slate的UI开发 (一)

1. 基本概念1.1. Slate是虚幻UI框架设计的底层,该框架中最基本的类是SWidget1.1.1.显然,我们容易注意到,直属于该框架的类拥有着指定的命名规则,即以S开头1.2. UMG, UWidget, Slate关联1.2.1. UMG:Unreal Motion Graphics UI Designer 虚幻的图形界面设计工具1.2.2. 单纯Sl…