[赛记] 多校A层冲刺NOIP2024模拟赛20

news/2024/11/13 12:15:24/文章来源:https://www.cnblogs.com/PeppaEvenPig/p/18538355

星际联邦 80pts

前连20条,后连20条80pts。。。

考虑正解,发现向前连最大,向后连最小会出现重边,所以避免出现这种情况,我们只需要在做完向前连最大以后,在向后连最小的时候连不是同一个连通块的即可;

时间复杂度:$ \Theta(n \log n) $ ,瓶颈在排序;

其实这个思想就是最小生成树的那个BUA算法(全名忘了);

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
long long n;
long long a[500005];
int po[500005];
struct sss{int f, t, w;
}e[1000005];
bool cmpw(sss x, sss y) {return x.w < y.w;
}
int cnt;
int fa[500005];
int find(int x) {if (x != fa[x]) fa[x] = find(fa[x]);return fa[x];
}
long long Kru() {sort(e + 1, e + 1 + cnt, cmpw);for (int i = 1; i <= n; i++) fa[i] = i;int sum = 0;long long ans = 0;for (int i = 1; i <= cnt; i++) {if (sum == n - 1) break;int x = find(e[i].f);int y = find(e[i].t);if (x != y) {fa[x] = y;ans += 1ll * e[i].w;sum++;}}return ans;
}
int main() {freopen("star.in", "r", stdin);freopen("star.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n;for (int i = 1; i <= n; i++) {cin >> a[i];}long long mi = a[n];int pos = n;for (int i = n - 1; i >= 1; i--) {e[++cnt] = {i, pos, (int)(mi - a[i])};if (mi > a[i]) {po[i] = pos;mi = a[i];pos = i;}}long long ma = a[1];pos = 1;for (int i = 2; i <= n; i++) {e[++cnt] = {i, pos, (int)(a[i] - ma)};if (ma < a[i]) {ma = a[i];pos = i;}if (po[i]) {e[++cnt] = {po[i], pos, (int)(a[po[i]] - ma)};}}cout << Kru();return 0;
}

和平精英 0pts

赛时的错解0pts;

考虑正解,发现如果我们枚举答案 $ x $,那么所有 $ \leq x $ 的都应该放到 $ or $ 集合里,所有 $ > x $ 的都应该放到 $ and $ 集合里,证明就考虑 $ x \And y \leq x, x | y > x $,这样就得到了一个 $ \Theta(qVn) $ 的复杂度;

考虑人类智慧优化,发现这玩意和 $ popcount $ 很像,于是考虑枚举答案的 $ popcount = x $,那么所有 $ popcount(a_i) < x $ 的都应该放到 $ or $ 集合里,所有 $ popcount(a_i) > x $ 的都应该放到 $ and $ 集合里,对于 $ popcount(a_i) = x $ 的数,这些数都应该相等(或者没有),且应该两个集合都要放,如果只有一个数的话就尝试分别放到两个集合中,最后判断一下两个集合的答案是否相等即可;

注意特判的情况,然后直接上线段树即可,时间复杂度:$ \Theta(n (\log n + \log V)) $;

点击查看代码
#include <iostream>
#include <cstdio>
#include <set>
#include <vector>
using namespace std;
int n, q;
int a[100005];
int sum[100005][35];
set<int> se;
vector<int> v;
namespace SEG{inline int ls(int x) {return x << 1;}inline int rs(int x) {return x << 1 | 1;}struct sss{int l, r, val[32], yu[32], huo[32];}tr[500005];inline void push_up(int s, int id) {if (tr[ls(id)].val[s] == -1e9) {tr[id].val[s] = tr[rs(id)].val[s];tr[id].yu[s] = tr[rs(id)].yu[s];tr[id].huo[s] = tr[rs(id)].huo[s];} else if (tr[rs(id)].val[s] == -1e9) {tr[id].val[s] = tr[ls(id)].val[s];tr[id].yu[s] = tr[ls(id)].yu[s];tr[id].huo[s] = tr[ls(id)].huo[s];} else {tr[id].val[s] = ((tr[ls(id)].val[s] == tr[rs(id)].val[s]) ? tr[ls(id)].val[s] : -2e9);tr[id].yu[s] = (tr[ls(id)].yu[s] & tr[rs(id)].yu[s]);tr[id].huo[s] = (tr[ls(id)].huo[s] | tr[rs(id)].huo[s]);}}void bt(int id, int l, int r) {tr[id].l = l;tr[id].r = r;for (int j = 0; j <= 30; j++) tr[id].val[j] = tr[id].yu[j] = tr[id].huo[j] = -1e9;if (l == r) return;int mid = (l + r) >> 1;bt(ls(id), l, mid);bt(rs(id), mid + 1, r);}void add(int s, int id, int pos, int d) {if (tr[id].l == tr[id].r) {tr[id].val[s] = d;tr[id].yu[s] = d;tr[id].huo[s] = d;return;}int mid = (tr[id].l + tr[id].r) >> 1;if (pos <= mid) add(s, ls(id), pos, d);else add(s, rs(id), pos, d);push_up(s, id);}void dfs(int id) {for (int j = 1; j <= 30; j++) {if (tr[id].huo[j - 1] == -1e9) continue;if (tr[id].huo[j] == -1e9) {tr[id].huo[j] = tr[id].huo[j - 1];} else {tr[id].huo[j] |= tr[id].huo[j - 1];}}for (int j = 29; j >= 0; j--) {if (tr[id].yu[j + 1] == -1e9) continue;if (tr[id].yu[j] == -1e9) {tr[id].yu[j] = tr[id].yu[j + 1];} else {tr[id].yu[j] &= tr[id].yu[j + 1];}}if (tr[id].l == tr[id].r) return;dfs(ls(id));dfs(rs(id));}void ask(int s, int id, int l, int r) {if (tr[id].l >= l && tr[id].r <= r) {se.insert(tr[id].val[s]);return;}int mid = (tr[id].l + tr[id].r) >> 1;if (r <= mid) ask(s, ls(id), l, r);else if (l > mid) ask(s, rs(id), l, r);else {ask(s, ls(id), l, mid);ask(s, rs(id), mid + 1, r);}}void ask_yu(int s, int id, int l, int r) {if (tr[id].l >= l && tr[id].r <= r) {if (tr[id].yu[s] != -1e9) v.push_back(tr[id].yu[s]);return;}int mid = (tr[id].l + tr[id].r) >> 1;if (r <= mid) ask_yu(s, ls(id), l, r);else if (l > mid) ask_yu(s, rs(id), l, r);else {ask_yu(s, ls(id), l, mid);ask_yu(s, rs(id), mid + 1, r);}}void ask_huo(int s, int id, int l, int r) {if (tr[id].l >= l && tr[id].r <= r) {if (tr[id].huo[s] != -1e9) v.push_back(tr[id].huo[s]);return;}int mid = (tr[id].l + tr[id].r) >> 1;if (r <= mid) ask_huo(s, ls(id), l, r);else if (l > mid) ask_huo(s, rs(id), l, r);else {ask_huo(s, ls(id), l, mid);ask_huo(s, rs(id), mid + 1, r);}}
}
using namespace SEG;
int main() {freopen("peace.in", "r", stdin);freopen("peace.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];}bt(1, 1, n);for (int i = 1; i <= n; i++) {int su = 0;for (int j = 0; j <= 30; j++) {sum[i][j] = sum[i - 1][j];if ((a[i] >> j) & 1) su++;}sum[i][su]++;add(su, 1, i, a[i]);}dfs(1);int l, r;for (int i = 1; i <= q; i++) {cin >> l >> r;if (l == r) {cout << "NO" << '\n';continue;}bool ans = false;for (int j = 0; j <= 30; j++) {if (sum[r][j] - sum[l - 1][j] == 0) {int yu = 0;v.clear();if (j != 30) ask_yu(j + 1, 1, l, r);for (int i = 1; i < v.size(); i++) {v[0] &= v[i];}if (v.empty()) continue;else yu = v[0];v.clear();int huo = 0;if (j != 0) ask_huo(j - 1, 1, l, r);for (int i = 1; i < v.size(); i++) {v[0] |= v[i];}if (v.empty()) continue;else huo = v[0];// cout << yu << ' ' << huo << endl;if (yu == huo) {ans = true;break;}continue;}int val = 0;se.clear();ask(j, 1, l, r);se.erase(-1e9);auto it = se.lower_bound(-2e9);if (it != se.end() && *it == -2e9) continue;if (se.size() != 1) continue;val = *se.begin();if (sum[r][j] - sum[l - 1][j] == 1) {int yu = 0;v.clear();if (j != 30) ask_yu(j + 1, 1, l, r);for (int i = 1; i < v.size(); i++) {v[0] &= v[i];}bool yy = false;if (!v.empty()) yu = v[0];else yy = true;v.clear();int huo = 0;if (j != 0) ask_huo(j - 1, 1, l, r);for (int i = 1; i < v.size(); i++) {v[0] |= v[i];}bool hh = false;if (!v.empty()) huo = v[0];else hh = true;int yyu = yu;if (!yu) yu = val;else yu &= val;if (!hh && yu == huo) {ans = true;break;}yu = yyu;huo |= val;if (!yy && yu == huo) {ans = true;break;}continue;}int yu = val;v.clear();if (j != 30) ask_yu(j + 1, 1, l, r);for (int i = 0; i < v.size(); i++) {yu &= v[i];}v.clear();int huo = val;if (j != 0) ask_huo(j - 1, 1, l, r);for (int i = 0; i < v.size(); i++) {huo |= v[i];}if (yu == huo) {ans = true;break;}}if (ans) cout << "YES" << '\n';else cout << "NO" << '\n';}return 0;
}

摆烂合唱 5pts

一个套路:表达式树

考虑建出来这个树(叶子是值,上面的节点都是运算符号),然后在这上面DP;

设 $ f_{x, 0/1} $ 表示 $ x $ 的左或右儿子值不同时,最终到 $ x $ 这个表达式的值不同的概率,那对于单个点的答案就是它到根路径上的 $ f_{x, 0/1} $ 乘积(具体看是左儿子还是右儿子);

例如更新 $ f_{x, 0} $,我们发现它的值和两个东西有关:

  1. 这一位的运算符;

  2. 它的右儿子值为 $ 1 $ 的概率;

对于 $ 1 $ 是好知道的,对于 $ 2 $,我们设 $ g_x $ 表示 $ x $ 这个节点值为 $ 1 $ 的概率,转移是容易的;

所以我们直接 $ DFS $,回溯时同时转移 $ f, g $,对于 $ f $ 的转移,只需简单分情况即可;

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

这个题主要在建树,可以参考一下代码(建树时记一个 $ fa $,完事回来的时候直接跳一步 $ fa $ 即可);

点击查看代码
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const long long mod = 998244353;
int n;
char s[2000005];
int len, tot, rt;
struct sss{int ls, rs, x, fa;
}tr[2000005];
long long f[2000005][2], g[2000005];
int val[2000005], cnt;
long long ksm(long long a, long long b) {long long ans = 1;while(b) {if (b & 1) ans = ans * a % mod;a = a * a % mod;b >>= 1;}return ans;
}
void dfs(int x) {if (tr[x].x == 0) {g[x] = ksm(2, mod - 2);return;}dfs(tr[x].ls);dfs(tr[x].rs);if (tr[x].x == 1) {f[x][0] = (1 - g[tr[x].rs] + mod) % mod;f[x][1] = (1 - g[tr[x].ls] + mod) % mod;g[x] = (g[tr[x].ls] + g[tr[x].rs] % mod - g[tr[x].ls] * g[tr[x].rs] % mod + mod) % mod;} else if (tr[x].x == 2) {f[x][0] = g[tr[x].rs];f[x][1] = g[tr[x].ls];g[x] = g[tr[x].ls] * g[tr[x].rs] % mod;} else if (tr[x].x == 3) {f[x][0] = 1;f[x][1] = 1;g[x] = ((g[tr[x].ls] * ((1 - g[tr[x].rs] + mod) % mod)) % mod + ((1 - g[tr[x].ls] + mod) % mod) * g[tr[x].rs] % mod) % mod;}
}
void afs(int x, long long ans) {if (tr[x].x == 0) {cout << ans << '\n';return;}afs(tr[x].ls, ans * f[x][0] % mod);afs(tr[x].rs, ans * f[x][1] % mod);
}
int main() {freopen("binary.in", "r", stdin);freopen("binary.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin >> n;if (n == 1) {cout << 1;return 0;}cin >> (s + 1);len = strlen(s + 1);int now = 0;for (int i = 1; i <= len; i++) {if (s[i] == '(') {tot++;if (!tr[now].ls) {tr[now].ls = tot;} else {tr[now].rs = tot;}tr[tot].fa = now;now = tot;}if (s[i] == ')') now = tr[now].fa;if (s[i] == 'x') {tot++;if (!tr[now].ls) {tr[now].ls = tot;} else {tr[now].rs = tot;}tr[tot].fa = now;}if (s[i] == '|') tr[now].x = 1;if (s[i] == '&') tr[now].x = 2;if (s[i] == '^') tr[now].x = 3;}dfs(1);afs(1, 1);return 0;
}

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

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

相关文章

旋转矢量合成,两个圆圈

import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import Circle, FancyArrowPatch from matplotlib.animation import FuncAnimation# 创建一个新图和两个坐标轴 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))# 设置坐标轴的等比例,确…

华三配置mstp

S1配置 stp mode mstp stp region-configuration region-name a revision-level 1 instance 1 vlan 10 instance 2 vlan 20 active region-configuration qu stp instance 1 root primary stp instance 2 root secondary stp global enable === S2配置 stp region-configuratio…

2024-2025-1 20241411 《计算机基础与程序设计》第七周学习总结

作业信息这个作业属于哪个课程 https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP/这个作业要求在哪里 https://www.cnblogs.com/rocedu/p/9577842.html#WEEK07这个作业的目标 数组与链表、基于数组和基于链表实现数据结构、无序表与有序表、树、图、子程序与参数作业正文…

并查集+最小生成树 学习笔记

图论系列: 前言: 咲いた野の花よ ああどうか教えておくれ 人は何故傷つけあって 争うのでしょう 相关题单: 题单1 题单2 题单3 题单4 一.并查集 1.基础定义与操作 (1)定义 并查集是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节…

三相电合成旋转矢量-动态图

import numpy as np import matplotlib.pyplot as plt from matplotlib.patches import Circle, FancyArrowPatch from matplotlib.animation import FuncAnimation# 创建一个新图和两个坐标轴 fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))# 设置坐标轴的等比例,确…

接雨水

using namespace std; //锻炼思维的题目。 int main(){ int t;cin>>t;while(t--){long long int n; // 使用 long long int 来处理可能的大数cin>>n;vector<long long int> a(n), l(n), r(n); // 同样,数组元素也应该是 long long intlong long int …

第 2 篇 Scrum 冲刺博客

作业要求这个作业属于哪个课程 计科34班这个作业的要求在哪里 团队作业4——项目冲刺这个作业的目标 1.站立式会议2.发布项目燃尽图3.每人的代码/文档签入记录4.适当的项目程序/模块的最新(运行)截图5.每日每人总结会议照片昨日已完成的工作/今天计划完成的工作成员 昨天已完…

Nuxt.js 应用中的 schema:extend事件钩子详解

title: Nuxt.js 应用中的 schema:extend事件钩子详解 date: 2024/11/10 updated: 2024/11/10 author: cmdragon excerpt: schema:extend 钩子使开发者能够扩展默认数据模式,为特定业务需求添加自定义字段和验证。 categories:前端开发tags:Nuxt 钩子 数据 扩展 自定义 验证…

nowcoder

Bin 3 1 1 2 2 2 1 40 1 6 5 3 4out 1 -37 3

实验3 类与对象

实验任务1: botton.hpp代码:1 #pragma once2 3 #include <iostream>4 #include <string>5 6 using std::string;7 using std::cout;8 9 // 按钮类 10 class Button { 11 public: 12 Button(const string &text); 13 string get_label() const; 14 …

2294: 【例29.3】 求小数的某一位

include <bits/stdc++.h> using namespace std; int n, m; long long sum=1, k; int main( ) { cin >> n >> m >> k; for (int i=1;i<=k;i++) { n*=10; sum=n/m; n%=m; } cout << sum<<endl; return 0; } 反思:这个代码我整体是错在把…

2024-2025-1 20241325 《计算机程序与设计》第七周学习总结

2024-2025-1 20241325 《计算机程序与设计》第七周学习总结 这个作业属于的课程<2024-2025-1-计算机基础与程序设计](https://edu.cnblogs.com/campus/besti/2024-2025-1-CFAP)> 这个作业要求在哪里:https://www.cnblogs.com/rocedu/p/9577842.html#WEEK07 这个作业的目标…