1.23 补题 寒假训练营

E 一起走很长的路!


输入描述

第一行输入两个整数 n,q(1≤n,q≤2×10^5),代表多米诺骨牌的个数和询问次数。 

第二行输入 n 个整数 a1,a2,…,an​(1≤ai≤10^9),表示多米诺骨牌的重量。

此后输入 q 行,每行输入两个整数 l,r(1≤l≤r≤n),代表一次询问。


输出描述

对于每一次询问,新起一行。输出一个整数,代表牛可乐最少需要调整的次数。每一次询问相互独立。


示例

输入:
4 2
2 1 2 7
2 3
1 4
输出:
1
2
说明:
  • 对于第一次询问,其中一种最优的调整方案是:将第 3 张多米诺骨牌的重量减少 1。

  • 对于第二次询问,其中一种最优的调整方案是:将第 3 张多米诺骨牌的重量增加 1、将第 4 张多米诺骨牌的重量减少 1,此时,各张多米诺骨牌的重量分别为 2, 1, 3, 6,符合题意,游戏完美。


思路

  1. 前缀和计算:首先计算数组 a 的前缀和 s,即 s[i] = s[i-1] + a[i]。前缀和的作用是快速计算任意区间的和。

  2. 构建线段树:我们需要构建一个线段树来维护区间内的最大值。线段树的每个节点维护以下信息:

    • l 和 r:表示当前节点所代表的区间范围。

    • maxv:表示当前区间内的最大值。

    • add:表示当前区间内的延迟标记(用于区间更新)。

  3. 初始化线段树:在构建线段树时,我们初始化每个叶子节点的值为 w[i] = a[i] - s[i-1]。这是因为我们需要维护的表达式是 a[i] - s[i-1]

  4. 查询处理:对于每个查询 [l, r],我们需要计算区间 [l+1, r] 内的最大值。具体步骤如下:

    • 首先,我们计算 tmp = s[l-1],即区间 [1, l-1] 的和。

    • 然后,我们对区间 [l+1, r] 进行区间更新,将每个元素的值增加 tmp。这是因为我们需要计算的是 a[i] - s[i-1] + s[l-1],即 a[i] - (s[i-1] - s[l-1])

    • 接着,我们查询区间 [l+1, r] 的最大值,并将其与 0 取最大值(因为题目要求输出非负数)。

    • 最后,我们将区间 [l+1, r] 的值恢复原状,即减去 tmp


代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, q;
int a[200005], s[200005], w[200005];
#define lc (p << 1)
#define rc (p << 1 | 1)
struct Node {int l, r;int maxv; int add;  
} tr[800005];
void pushup(int p) {tr[p].maxv = max(tr[lc].maxv, tr[rc].maxv);
}
void pushdown(int p) {if (tr[p].add != 0) {tr[lc].maxv += tr[p].add; tr[rc].maxv += tr[p].add;tr[lc].add += tr[p].add; tr[rc].add += tr[p].add; tr[p].add = 0;            }
}
void build(int p, int l, int r) {tr[p] = {l, r, w[l], 0};if (l == r) return;int m = (l + r) >> 1;build(lc, l, m);build(rc, m + 1, r);pushup(p);
}
//区间更新
void modify(int p, int x, int y, int k) {if (x <= tr[p].l && tr[p].r <= y) {tr[p].maxv += k;tr[p].add += k;return;}pushdown(p); int m = (tr[p].l + tr[p].r) >> 1;if (x <= m) modify(lc, x, y, k);if (y > m) modify(rc, x, y, k);pushup(p);
}
int query(int p, int x, int y) {if (x <= tr[p].l && tr[p].r <= y) {return tr[p].maxv;}pushdown(p);int m = (tr[p].l + tr[p].r) >> 1;int res = -1e9; if (x <= m) res = max(res, query(lc, x, y));if (y > m) res = max(res, query(rc, x, y));return res;
}
signed main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> n >> q;for (int i = 1; i <= n; i++) {cin >> a[i];s[i] = s[i - 1] + a[i];}for (int i = 1; i <= n; i++) {w[i] = a[i] - s[i - 1];}build(1, 1, n);while (q--) {int l, r;cin >> l >> r;if (l == r) {cout << 0 << '\n';continue;}int tmp = s[l - 1];modify(1, l + 1, r, tmp);int ans = max(0LL, query(1, l + 1, r));cout << ans << '\n';modify(1, l + 1, r, -tmp);}return 0;
}

C 字符串外串

题目描述

牛可乐定义字符串 ss 的可爱度为最大的整数 k,满足存在一个长度为 k 的连续子串 a,和一个长度为 k 的不连续子序列 b,满足 a=b。

现在,牛可乐给定你两个整数 n,m,并且询问你是否存在长度为 n、仅由小写字母构成的字符串 t,使得 t 的可爱度恰好等于 m。如果存在,输出任意一个符合条件的字符串 t。

定义:
  1. 连续子串:从原字符串中连续选择一段字符(可以全选、可以不选)得到的新字符串。

  2. 不连续子序列:至少由两段不相邻的非空子串构成。

输入描述:

每个测试文件均包含多组测试数据。第一行输入一个整数 T(1≤T≤10^4)代表数据组数,每组测试数据描述如下:

在一行上输入两个整数 n,m(3≤m≤n≤2×10^5)代表限制。

除此之外,保证单个测试文件的 n 之和不超过 2×10^5。

输出描述:

如果答案不存在,直接输出 NO;否则,在第一行输出 YES,在第二行输出一个仅由小写字母构成的字符串 ss,代表构造出的字符串。


示例

输入:

2
4 3
3 3

输出:

YES
abcc
NO

解释:

1.对于第一组测试数据:

字符串 abcc 的连续子串 abc 和不连续子序列 abc 满足条件。

因此,可爱度为 3,符合要求。

2.对于第二组测试数据:

无法构造满足条件的字符串,输出 NO


数据范围

  • 1≤T≤10^4

  • 3≤m≤n≤2×10^5

  • 单个测试文件的 n 之和不超过 2×10^5


思路

如果 n==m,则无法构造满足条件的字符串,因为不连续子序列至少需要两段不相邻的子串,而连续子串的长度为 n,无法满足条件。

如果 n−m>26,则无法构造满足条件的字符串,因为字母种类有限,无法保证不连续子序列的构造。

否则,可以通过构造一个字符串,使得其连续子串和不连续子序列的长度为 m。

构造方法

使用循环字母表构造字符串,使得字符串的前 n−m 个字符是唯一的,后面的字符重复前面的字符。

这样可以保证存在一个长度为 m 的连续子串和一个长度为 m 的不连续子序列。

代码

#include <bits/stdc++.h>
using namespace std;
#define int long long
int t;
signed main()
{ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);cin >> t;while (t--){int n, m;cin >> n >> m;if (n == m || n - m > 26){cout << "NO" << "\n";continue;}cout << "YES" << "\n";for (int i = 0; i < n; i++){cout << (char)('a' + i % (n - m));}cout << "\n";}
}

M 那是我们的影子 

示例

输入:

4
6
1???56
456789
7891??
3
???
???
?11
3
123
456
789
3
723
18?
?9?

输出:

2
0
1
6

解释:

  1. 对于第一组测试数据,合法的情况有两种:

    • 第一种:

      1 2 3 4 5 6
      4 5 6 7 8 9
      7 8 9 1 2 3
    • 第二种:

      1 3 2 4 5 6
      4 5 6 7 8 9
      7 8 9 1 3 2
  2. 对于第二组测试数据,由于初始的矩阵中存在两个 1,所以无论如何构造都不合法。

  3. 对于第三组测试数据,不需要填入任何数字,所以只有唯一一种合法解。

  4. 对于第四组测试数据,有 6 种合法的填法。


数据范围

  • 1≤T≤100

  • 3≤n≤10^5

  • 单个测试文件的 n 之和不超过 3×10^5


思路

代码 

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;
signed main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int t;cin >> t;while (t--) {int n;cin >> n;vector<string> s(3);for (auto &i : s) cin >> i;int flag = 1;vector<set<int>> st(3);vector<int> a(n);for (int j = 0; j < n; j++) {set<int> t;for (int i = 0; i < 3; i++) {if (s[i][j] == '?') {a[j]++;continue;}s[i][j] -= '0';if (t.count(s[i][j])) flag = 0;t.insert(s[i][j]);}st[j % 3].merge(t);}vector<int> sst;for (auto &i : st) {if (i.size() > 3) flag = 0;int x = 0;for (auto &j : i) x ^= 1 << j;sst.push_back(x);}if (!flag) {cout << 0 << endl;continue;}int S = 1;for (int i = 3; i < n; i++) {if (a[i] == 2) S = S * 2 % MOD;if (a[i] == 3) S = S * 6 % MOD;}vector<int> v(9);iota(v.begin(), v.end(), 1);int sum = 0;do {int flag = 1;for (int i = 0; i < 3; i++) {for (int j = 0; j < 3; j++) {if (s[i][j] == '?') continue;int x = i + j * 3;if (s[i][j] != v[x]) flag = 0;}}int x;x = (1 << v[0]) + (1 << v[1]) + (1 << v[2]);if (x != (x | sst[0])) flag = 0;x = (1 << v[3]) + (1 << v[4]) + (1 << v[5]);if (x != (x | sst[1])) flag = 0;x = (1 << v[6]) + (1 << v[7]) + (1 << v[8]);if (x != (x | sst[2])) flag = 0;if (!flag) continue;sum = (sum + S) % MOD;} while (next_permutation(v.begin(), v.end()));cout << sum << '\n';}return 0;
}

I 一起看很美的日落!

题目描述

牛可乐有一棵由 n 个结点构成的树,第 i 个节点的权值为 ai。

我们定义一个连通块 V 的权值为:

  • 当前连通块中两两结点的权值异或和,即 ∑i,j∈V(ai⊕aj)。

你需要计算全部连通块的权值之和。由于答案可能很大,请将答案对 10^9+7 取模后输出。

此题中的连通块定义为:对于树上的任意一个点集 S,如果 S 中的任意两点 u,v 之间存在一条路径,且路径上的所有点都在 S 中,则称 S 是一个连通块。


输入描述

第一行输入一个整数 n(1≤n≤105),代表树上的节点数量。

第二行输入 n 个整数 a1,a2,…,an(1≤ai≤109),代表每个节点的权值。

此后 n−1 行,第 i 行输入两个整数 ui,vi(1≤ui,vi≤n,ui≠vi),代表树上第 i 条边连接节点 ui 和 vi。


输出描述

输出一个整数,代表全部连通块的权值和。答案可能很大,请将答案对 10^9+7 取模后输出。


示例 1

输入
3
5 2 1
1 2
1 3
输出
50
解释

在这个样例中,一共有 6 个连通块,每一个连通块的权值依次为:

  • {1},记为 V1​,权值为 a1⊕a1=0;

  • {1,2},记为 V2,权值为 (a1⊕a1)+(a1⊕a2)+(a2⊕a1)+(a2⊕a2)=14;

  • {1,3},记为 V3,权值为 (a1⊕a1)+(a1⊕a3)+(a3⊕a1)+(a3⊕a3)=8;

  • {1,2,3},记为 V4,权值为 28;

  • {2},记为 V5,权值为 a2⊕a2=0;

  • {3},记为 V6​,权值为 a3⊕a3=0。

所以,全部连通块的权值和为 0+14+8+28+0+0=50。


示例 2

输入
4
5 6 3 1
1 2
1 3
2 4
输出
142

思路

每个连通块的权值是所有点对的异或和。

直接枚举所有连通块并计算权值会超时,因为连通块的数量是指数级的。

需要利用树的性质和动态规划来优化计算。

动态规划

定义 dp[u]dp[u] 表示以 u 为根的子树中所有连通块的权值和。

定义 cnt[b][w][u] 表示以 u 为根的子树中,第 w 位为 b 的节点数。

定义 sz[u] 表示以 u 为根的子树中节点数。

DFS 遍历

在 DFS 过程中,更新 dp[u]、cnt[b][w][u] 和 sz[u]。

对于每个子节点 v,计算其对 dp[u] 的贡献,并更新 cnt[b][w][u] 和 sz[u]。

最终答案

所有连通块的权值和为 ans×2mod  (10^9+7)

 代码

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
const int N = 1e5 + 1;
int dp[N]; 
int cnt[2][30][N];
int sz[N]; 
int ans = 0; 
void dfs(int u, int fa, const vector<vector<int>>& adj, const vector<int>& a) {sz[u] = 1;for (int w = 0; w < 30; w++) {if ((a[u] >> w) & 1) {cnt[1][w][u] = 1;} else {cnt[0][w][u] = 1;}}for (int v : adj[u]) {if (v == fa) continue;dfs(v, u, adj, a);dp[u] = (dp[u] + 1LL * dp[v] * sz[u] % mod + 1LL * dp[u] * sz[v] % mod) % mod;for (int w = 0; w < 30; w++) {int t = (1 << w) % mod;dp[u] = (dp[u] + 1LL * t * cnt[0][w][u] % mod * cnt[1][w][v] % mod) % mod;dp[u] = (dp[u] + 1LL * t * cnt[1][w][u] % mod * cnt[0][w][v] % mod) % mod;cnt[0][w][u] = (cnt[0][w][u] + 1LL * cnt[0][w][u] * sz[v] % mod + 1LL * cnt[0][w][v] * sz[u] % mod) % mod;cnt[1][w][u] = (cnt[1][w][u] + 1LL * cnt[1][w][u] * sz[v] % mod + 1LL * cnt[1][w][v] * sz[u] % mod) % mod;}sz[u] = (sz[u] + 1LL * sz[v] * sz[u] % mod) % mod;}ans = (ans + dp[u]) % mod;
}
signed main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int n;cin >> n;vector<int> a(n + 1);vector<vector<int>> adj(n + 1);for (int i = 1; i <= n; i++) {cin >> a[i];assert(a[i] >= 1 && a[i] <= 1e9);}for (int i = 1; i < n; i++) {int u, v;cin >> u >> v;adj[u].push_back(v);adj[v].push_back(u);}memset(dp, 0, sizeof(dp));memset(cnt, 0, sizeof(cnt));memset(sz, 0, sizeof(sz));ans = 0;dfs(1, 0, adj, a);cout << ans * 2 % mod << '\n';return 0;
}

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

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

相关文章

从入门到精通:RabbitMQ的深度探索与实战应用

目录 一、RabbitMQ 初相识 二、基础概念速览 &#xff08;一&#xff09;消息队列是什么 &#xff08;二&#xff09;RabbitMQ 核心组件 三、RabbitMQ 基本使用 &#xff08;一&#xff09;安装与环境搭建 &#xff08;二&#xff09;简单示例 &#xff08;三&#xff09;…

基于vscode的cppcmake调试环境配置

1. 创建项目文件 创建cpp文件及CMakeLists.txt文件 helloOpenCV.cpp #include <opencv2/opencv.hpp> int main() {// 创建图像&#xff0c;初始化为黑色cv::Mat image cv::Mat::zeros(200, 300, CV_8UC3);// 设置为纯绿色 (BGR格式&#xff1a;0, 255, 0)image.setTo…

后端面试题分享第一弹(状态码、进程线程、TCPUDP)

后端面试题分享第一弹 1. 如何查看状态码&#xff0c;状态码含义 在Web开发和调试过程中&#xff0c;HTTP状态码是了解请求处理情况的重要工具。 查看状态码的步骤 打开开发者工具&#xff1a; 在大多数浏览器中&#xff0c;您可以通过按下 F12 键或右键单击页面并选择“检查…

(1)STM32 USB设备开发-基础知识

开篇感谢&#xff1a; 【经验分享】STM32 USB相关知识扫盲 - STM32团队 ST意法半导体中文论坛 单片机学习记录_桃成蹊2.0的博客-CSDN博客 USB_不吃鱼的猫丿的博客-CSDN博客 1、USB鼠标_哔哩哔哩_bilibili usb_冰糖葫的博客-CSDN博客 USB_lqonlylove的博客-CSDN博客 USB …

win32汇编环境,对话框程序中使用进度条控件

;运行效果 ;win32汇编环境,对话框程序中使用进度条控件 ;进度条控件主要涉及的是长度单位,每步步长,推进的时间。 ;比如你的长度是1000,步长是100,每秒走1次,则10秒走完全程 ;比如你的长度是1000,步长是10,每秒走1次,则100秒走完全程,但每格格子的长度与上面一样 ;以下…

CrypTen——基于pytorch的隐私保护机器学习框架

目录 一、CrypTen概述 二、应用场景 三、CrypTen优势 四、CrypTen技术解析 1.基于pytorch的构建基础 2.核心密码学原语 3.加密模型训练流程 五、传统隐私保护技术与CrypTen的对比 1.传统隐私保护技术介绍 2.CrypTen与传统隐私保护技术的区别 六、CrypTen的环境配置…

电梯系统的UML文档11

场景 7.3 紧急制动 3 –当电梯停止在某一楼层时&#xff0c;如果命令门打开&#xff0c;但是门不开&#xff0c;则紧急制动将触发。 图 16: 场景 7.3- 紧急制动 - 门将不开启当电梯停止在目的层 场景 7.4 紧急制动 4 –如果电梯移动时门打开&#xff0c;紧急制动将触发。 图 1…

【Elasticsearch 基础入门】Centos7下Elasticsearch 7.x安装与配置(单机)

Elasticsearch系列文章目录 【Elasticsearch 基础入门】一文带你了解Elasticsearch&#xff01;&#xff01;&#xff01;【Elasticsearch 基础入门】Centos7下Elasticsearch 7.x安装与配置&#xff08;单机&#xff09; 目录 Elasticsearch系列文章目录前言单机模式1. 安装 J…

正点原子Linux 移植USB Wifi模块MT7601U驱动(上)

目录 下载驱动MT7601驱动文件中重要的几个文件1.README_STA_usb2.sta_ate_iwpriv_usage.txt3.config.mk4.Makefile 移植过程编译驱动成ko文件复制到根文件系统里驱动加载失败常见原因A. DMA缓存大小不够B. RT2870STA.dat文件没配置好 模块加载测试开启无线网卡并设置IP地址 参考…

Linux相关概念和易错知识点(26)(命名管道、共享内存)

目录 1.命名管道 &#xff08;1&#xff09;匿名管道 -> 命名管道 ①匿名管道 ②命名管道 &#xff08;2&#xff09;命名管道的使用 ①创建和删除命名管道文件 ②命名管道文件的特性 ③命名管道和匿名管道的区别 &#xff08;3&#xff09;用命名管道实现进程间通信…

【时时三省】(C语言基础)对比一组函数

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 对比一组函数 比如对比一下scanf fscanf sscanf和printf fprintf sprintf scanf 针对标准输入的格式化的输入语句 其实它针对的是stdin fscanf 针对所有输入流的格式化的输入语句 它是针对s…

Leecode刷题C语言之组合总和②

执行结果:通过 执行用时和内存消耗如下&#xff1a; int** ans; int* ansColumnSizes; int ansSize;int* sequence; int sequenceSize;int** freq; int freqSize;void dfs(int pos, int rest) {if (rest 0) {int* tmp malloc(sizeof(int) * sequenceSize);memcpy(tmp, seque…

汽车网络信息安全-ISO/SAE 21434解析(下)

目录 第十二~十四章 - 后开发阶段 1. 十二章节 - 生产 2. 十三章节 - 运营与维护 网络安全事件响应 更新 3. 十四章节 - 结束网络安全支持和停用 结束网络安全支持 报废 第十五章 - TARA分析方法 1. 概述 2. 资产识别 3. 威胁场景识别 4. 影响评级 5. 攻击路径分…

[java] java基础-字符串篇

目录 API String 创建字符串对象的两种方式&#xff1a; Java的内存模型 字符串常量池&#xff08;串池&#xff09;存放地址 两种构造方法的内存分析 String的常用方法 号比较的是什么 字符串比较&#xff08;比较字符串的数据值&#xff09; 遍历字符串 StringBui…

Unity中关于实现 管道水流+瀑布流动+大肠蠕动效果笔记

Unity中关于实现 管道水流瀑布流动大肠蠕动效果笔记 效果展示&#xff1a; 参考资料及链接&#xff1a; 1、如何在 Unity 中创建水效果 - 水弯曲教程 https://www.youtube.com/watch?v3CcWus6d_B8 关于补充个人技能中&#xff1a;顶点噪波影响网格着色器配合粒子实现水特效 …

Couchbase UI: Indexes

在Couchbase中&#xff0c;索引的这些指标可以帮助你评估索引的性能和状态。下面是每个指标的详细解释&#xff0c;以及如何判断索引的有效性&#xff1a; 1. Index Name&#xff08;索引名称&#xff09; 描述&#xff1a;每个索引都有一个唯一的名称。这个名称通常会包括表…

redis的分片集群模式

redis的分片集群模式 1 主从哨兵集群的问题和分片集群特点 主从哨兵集群可应对高并发写和高可用性&#xff0c;但是还有2个问题没有解决&#xff1a; &#xff08;1&#xff09;海量数据存储 &#xff08;2&#xff09;高并发写的问题 使用分片集群可解决&#xff0c;分片集群…

第一届“启航杯”网络安全挑战赛WP

misc PvzHE 去这个文件夹 有一张图片 QHCTF{300cef31-68d9-4b72-b49d-a7802da481a5} QHCTF For Year 2025 攻防世界有一样的 080714212829302316092230 对应Q 以此类推 QHCTF{FUN} 请找出拍摄地所在位置 柳城 顺丰 forensics win01 这个软件 云沙盒分析一下 md5 ad4…

ThreadLocal概述、解决SimpleDateFormat出现的异常、内存泄漏、弱引用、remove方法

①. ThreadLocal简介 ①. ThreadLocal是什么 ①. ThreadLocal本地线程变量,线程自带的变量副本(实现了每一个线程副本都有一个专属的本地变量,主要解决的就是让每一个线程绑定自己的值,自己用自己的,不跟别人争抢。通过使用get()和set()方法,获取默认值或将其值更改为当前线程…

蓝桥杯模拟算法:多项式输出

P1067 [NOIP2009 普及组] 多项式输出 - 洛谷 | 计算机科学教育新生态 这道题是一道模拟题&#xff0c;我们需要分情况讨论&#xff0c;我们需要做一下分类讨论 #include <iostream> #include <cstdlib> using namespace std;int main() {int n;cin >> n;for…