[赛记] csp-s模拟8 csp-s模拟9

news/2024/10/10 12:13:31

HZOI大作战 15pts

赛时暴力跳父亲15pts;

正解:发现在树上对于向上找大于这个数的操作具有随意划分性,所以考虑倍增,设 $ f_{i, j} $ 表示从 $ i $ 这个点向上跳 $ 2^j $ 个比它大的数能跳到哪里,于是我们只需处理出向上跳一个(也就是 $ f_{i, 0} $)的,然后 $ ST $ 表预处理即可;

具体地,对于一个点 $ a_i $:

如果 $ a_{fa_{i}} > a_i $,就 $ f_{i, 0} = fa_{i} $;

如果 $ a_{fa_{i}} = a_i $,就 $ f_{i, 0} = f_{fa_i, 0} $;

否则用倍增找出第一个比它大的赋值即可;

对于查询,思路基本一样;

时间复杂度: $ \Theta(n \log n) $;

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
int n, q;
int a[500005];
struct sss{int t, ne;
}e[2000005];
int h[2000005], cnt;
void add(int u, int v) {e[++cnt].t = v;e[cnt].ne = h[u];h[u] = cnt;
}
int f[500005][21], dep[500005];
void dfs(int x, int fa) {if (a[x] < a[fa]) f[x][0] = fa;else if (a[x] == a[fa]) f[x][0] = f[fa][0];else if (a[x] > a[fa]) {int y = fa;for (int i = 19; i >= 0; i--) {if (a[f[y][i]] <= a[x] && f[y][i] != 0) y = f[y][i];}f[x][0] = f[y][0];}for (int j = 1; j <= 19; j++) {f[x][j] = f[f[x][j - 1]][j - 1];}dep[x] = dep[fa] + 1;for (int i = h[x]; i; i = e[i].ne) {int u = e[i].t;if (u == fa) continue;dfs(u, x);}
}
int w(int u, int v, int c) {int ans = 0;if (c < a[u]) {ans++;} else if (c > a[u]) {for (int i = 19; i >= 0; i--) {if (a[f[u][i]] <= c && f[u][i] != 0) u = f[u][i];}}for (int i = 19; i >= 0; i--) {if (dep[f[u][i]] >= dep[v]) {u = f[u][i];ans += pow(2, i);}}return ans;
}
int main() {freopen("accepted.in", "r", stdin);freopen("accepted.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> q;for (int i = 1; i <= n; i++) {cin >> a[i];}int x, y;for (int i = 1; i <= n - 1; i++) {cin >> x >> y;add(x, y);add(y, x);}dfs(1, 0);int u, v, c;for (int i = 1; i <= q; i++) {cin >> u >> v >> c;cout << w(u, v, c) << '\n';}return 0;
}

邻面合并 70pts

赛时错解70pts;

正解:看见 $ m \leq 8 $,考虑状压;

设 $ f_{i, j} $ 表示考虑到第 $ i $ 行,当前行的连接状态是 $ j $ 时的最小划分数;

这里的连接状态是指,对于 $ j $ 的一个二进制位 $ j_x $( $ x $ 从 $ 0 $ 开始计数 ),若 $ j_x = 1 $ 则代表 $ a_{i, x + 1} $ 与 $ a_{i, x + 2} $ 连接,否则不连接;

转移直接转(lxyt说),但我分了很多情况,最后好像还是不对,但过了。。。

时间复杂度:$ \Theta(n \times 2^{2x - 2}) $;

代码仅供参考;

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n, m;
int a[105][105];
int f[105][(1 << 9)];
bool ck(int i, int j) {for (int x = 0; x <= m - 2; x++) {if (a[i][x + 1] + a[i][x + 2] < 2 && ((j >> x) & 1)) return false;}return true;
}
int main() {freopen("merging.in", "r", stdin);freopen("merging.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n >> m;for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {cin >> a[i][j];}}memset(f, 0x3f, sizeof(f));for (int j = 0; j < (1 << (m - 1)); j++) {f[0][j] = 0;}for (int i = 1; i <= n; i++) {for (int j = 0; j < (1 << (m - 1)); j++) {if (!ck(i, j)) continue;for (int k = 0; k < (1 << (m - 1)); k++) {if (!ck(i - 1, k)) continue;int res = f[i - 1][k];int ej = -1;int ek = -1;int x = 1;bool vis = false;while(x <= m) {ej = m;ek = m;if (!a[i][x]) {x++;vis = false;continue;}if (!a[i][x - 1] && ((k >> (x - 2)) & 1)) vis = true;for (int t = x; t <= m; t++) {if (!((j >> (t - 1)) & 1)) {ej = t;break;}}if (((k >> (x - 2)) & 1)) {ek = ej + 1;} else {for (int t = x; t <= m; t++) {if (i == 1) {ek = ej + 1;break;}if (!((k >> (t - 1)) & 1)) {if (!a[i - 1][t]) ek = ej + 1;else ek = t;break;}}}if (ej != ek || vis) res++;x = ej + 1;}f[i][j] = min(f[i][j], res);}}}int ans = 0x3f3f3f3f;for (int i = 0; i < (1 << (m - 1)); i++) {ans = min(ans, f[n][i]);}cout << ans;return 0;
}

光线追踪 30pts;

赛时最暴力的暴力30pts;

正解:可以发现每次插入的矩形只有左边和下边的边能够产生贡献;

所以用斜率当下标建一棵线段树,然后区间插入+单点查询即可解决;

难点:想到用斜率当下标建一棵线段树(可以用 $ double $ 类型当下标,但最好还是离线将所有要用到的斜率离散化一下);

注意特判斜率等于零和不存在的情况;

时间复杂度:设一共有 $ k $ 个不同的斜率,则时间复杂度为: $ \Theta(q \log k) $;

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int q;
double a[1000005];
int cnt;
int qx[500005], qy[500005], hx[500005], hy[500005], x[500005], y[500005], s[500005];
pair<int, int> pcm(pair<int, int> a, pair<int, int> b) {if (a.first < b.first) return a;if (a.first > b.first) return b;if (a.first == b.first) {if (a.second > b.second) return a;else return b;}
}
namespace SEG{inline int ls(int x) {return x << 1;}inline int rs(int x) {return x << 1 | 1;}struct sss{int l, r;pair<int, int> mi, lz;}tr[2][5000005];inline void push_down(int s, int id) {if (tr[s][id].lz.first != 2e9) {tr[s][ls(id)].lz = pcm(tr[s][ls(id)].lz, tr[s][id].lz);tr[s][rs(id)].lz = pcm(tr[s][rs(id)].lz, tr[s][id].lz);tr[s][ls(id)].mi = pcm(tr[s][ls(id)].mi, tr[s][id].lz);tr[s][rs(id)].mi = pcm(tr[s][rs(id)].mi, tr[s][id].lz);tr[s][id].lz = {2e9, 0};}}void bt(int s, int id, int l, int r) {tr[s][id].l = l;tr[s][id].r = r;tr[s][id].mi = {2e9, 0};tr[s][id].lz = {2e9, 0};if (l == r) return;int mid = (l + r) >> 1;bt(s, ls(id), l, mid);bt(s, rs(id), mid + 1, r);}void add(int s, int id, int l, int r, pair<int, int> d) {if (tr[s][id].l >= l && tr[s][id].r <= r) {tr[s][id].mi = pcm(tr[s][id].mi, d);tr[s][id].lz = pcm(tr[s][id].lz, d);return;}push_down(s, id);int mid = (tr[s][id].l + tr[s][id].r) >> 1;if (l <= mid) add(s, ls(id), l, r, d);if (r > mid) add(s, rs(id), l, r, d);}pair<int, int> ask(int s, int id, int pos) {if (tr[s][id].l == tr[s][id].r) return tr[s][id].mi;push_down(s, id);int mid = (tr[s][id].l + tr[s][id].r) >> 1;if (pos <= mid) return ask(s, ls(id), pos);else return ask(s, rs(id), pos);}
}
pair<int, int> px, py;
int main() {freopen("raytracing.in", "r", stdin);freopen("raytracing.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> q;px = {2e9, 0};py = {2e9, 0};for (int i = 1; i <= q; i++) {cin >> s[i];if (s[i] == 1) {cin >> qx[i] >> qy[i] >> hx[i] >> hy[i];if (qy[i] && hx[i]) a[++cnt] = 1.00 * qy[i] / hx[i];if (qy[i] && qx[i]) a[++cnt] = 1.00 * qy[i] / qx[i];if (hy[i] && qx[i]) a[++cnt] = 1.00 * hy[i] / qx[i];}if (s[i] == 2) {cin >> x[i] >> y[i];if (x[i] == 0 || y[i] == 0) continue;a[++cnt] = 1.00 * y[i] / x[i];}}a[++cnt] = 0.0;a[++cnt] = 1000000000.00;sort(a + 1, a + 1 + cnt);cnt = unique(a + 1, a + 1 + cnt) - a - 1;SEG::bt(0, 1, 1, cnt);SEG::bt(1, 1, 1, cnt);for (int i = 1; i <= q; i++) {if (s[i] == 1) {if (qx[i] == 0) {py = pcm(py, {qy[i], i});SEG::add(0, 1, lower_bound(a + 1, a + 1 + cnt, 1.00 * qy[i] / hx[i]) - a, lower_bound(a + 1, a + 1 + cnt, 1000000000.00) - a, {qy[i], i});continue;}if (qy[i] == 0) {px = pcm(px, {qx[i], i});SEG::add(1, 1, lower_bound(a + 1, a + 1 + cnt, 0.0) - a, lower_bound(a + 1, a + 1 + cnt, 1.00 * hy[i] / qx[i]) - a, {qx[i], i});continue;}SEG::add(0, 1, lower_bound(a + 1, a + 1 + cnt, 1.00 * qy[i] / hx[i]) - a, lower_bound(a + 1, a + 1 + cnt, 1.00 * qy[i] / qx[i]) - a, {qy[i], i});SEG::add(1, 1, lower_bound(a + 1, a + 1 + cnt, 1.00 * qy[i] / qx[i]) - a, lower_bound(a + 1, a + 1 + cnt, 1.00 * hy[i] / qx[i]) - a, {qx[i], i});}if (s[i] == 2) {if (x[i] == 0) {cout << py.second << '\n';continue;}if (y[i] == 0) {cout << px.second << '\n';continue;}double k = 1.00 * y[i] / x[i];int pos = lower_bound(a + 1, a + 1 + cnt, k) - a;pair<int, int> yy = SEG::ask(0, 1, pos);pair<int, int> xx = SEG::ask(1, 1, pos);double nowx = 1.00 * yy.first / k;if (nowx < 1.00 * xx.first) {cout << yy.second << '\n';} else if (nowx > 1.00 * xx.first) {cout << xx.second << '\n';} else {cout << max(yy.second, xx.second) << '\n';}}}return 0;
}

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

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

相关文章

[编程笔记] 当前上下文中不存在名称ViewBag

当前上下文中不存在名称"ViewBag",很多ViewBag、@Html.Partial、@Html.FunctionBar() 等这些地方都报波浪线了,提示不存在这个名称,但是代码是可以运行的最近在弄另外一个项目,很长一段时间没接触MVC了,Visual Studio 2022识别cshtml文件的时候,出了一点故障!…

MSSQL-从字符串转换日期和/或时间时,转换失败

1、报错的sql为: select ID,Test_time as 时间, from ProcessData where convert(datetime,test_time,120) between convert(datetime, 2020-10-10, 120) and convert(datetime, 2024-10-11, 120) 它是将Test_time转化为datetime格式,再用between进行比较; 2、报错原因:…

Pytorch常用代码段汇总

Pytorch常用代码段来源: https://zhuanlan.zhihu.com/p/104019160 PyTorch最好的资料是官方文档。本文是PyTorch常用代码段,在参考资料[1](张皓:PyTorch Cookbook)的基础上做了一些修补,方便使用时查阅。 1. 基本配置 导入包和版本查询 import torch import torch.nn as nn…

manim边学边做--无向图

无向图属于数学中的图论这一学科, 所谓无向图G,就是由顶点集V(非空集合)和边集E(由V中元素构成的无序二元组的集合)组成的图, 可表示为G=(V,E)。 在无向图中,边没有方向,即从顶点A到顶点B的边与从顶点B到顶点A的边是相同的。 无向图简洁直观,常用于描述社交网络,交通…

[持续更新]程序员每天会阅读哪些技术网站(带链接)来提升自己?

本文原文来自[持续更新]程序员每天会阅读哪些技术网站(带链接)来提升自己? 国内的网站 这些国内技术网站和社区涵盖了编程语言、算法、职业规划、云计算、AI等多方面的内容,可以获取最新的技术资讯、学习资源和开发经验。当然目前国内的技术社区的内容还是相当的鱼龙混杂。CS…

VScode远程访问虚拟机

下载vscode插件Remote Development 该插件包括了wsl,remote ssh 等四个插件,均是用于远程访问虚拟机。 通过ssh访问虚拟机 下载后在工具栏索引可以看到如下标识,按顺序点击进入,然后在“3”显示的搜索框通过“ ssh username@ipAddr”访问,这是方法一。 方法二,还可以通…

20222317 2024-2025-1《网络与系统攻防技术》实验一实验报告

一、实验内容 本次实验的对象是一个名为pwn1的linux可执行文件。该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们本次实验将学习两种方…

似然

似然问题背景:我们观察到随机变量 \(Y\) 的值 \(y\),而 \(Y\) 的概率密度函数 \(f(y; \theta)\) 已知,但依赖于参数 \(\theta\)。 参数 \(\theta\) 来自参数空间 \(\Theta\),观测数据来自样本空间 \(\mathcal{Y}\)。 目标是根据观测数据 \(y\),推断参数 \(\theta\) 的可能…