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.mzph.cn/bicheng/69263.shtml

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

相关文章

【中间件快速入门】什么是Redis

现在后端开发会用到各种中间件&#xff0c;一不留神项目可能在哪天就要用到一个我们之前可能听过但是从来没接触过的中间件&#xff0c;这个时候对于开发人员来说&#xff0c;如果你不知道这个中间件的设计逻辑和使用方法&#xff0c;那在后面的开发和维护工作中可能就会比较吃…

金晟新能源由盈转亏:毛利率下滑产能利用率不佳,关联交易持续增加

《港湾商业观察》黄懿 近期&#xff0c;广东金晟新能源股份有限公司&#xff08;下称“金晟新能源”&#xff09;递交了招股书&#xff0c;拟冲刺港交所IPO&#xff0c;中金公司、招银国际为联席保荐人。 金晟新能源处于电池回收的新兴大势行业&#xff0c;但是&#xff0c;受…

RTMP|RTSP播放器只解码视频关键帧功能探讨

技术背景 我们在做RTMP|RTSP直播播放器的时候&#xff0c;遇到过这样的技术诉求&#xff0c;在一些特定的应用场景中&#xff0c;可能只需要关键帧的信息&#xff0c;例如视频内容分析系统&#xff0c;可能只对关键帧进行分析&#xff0c;以提取特征、检测对象或场景变化。鉴于…

2K高刷电竞显示器怎么选?

2K高刷电竞显示器怎么选&#xff1f;哪个价格适合你&#xff1f;哪个配置适合你呢&#xff1f; 1.HKC G27H2Pro - 2K高刷电竞显示器怎么选 外观设计 - HKC G27H2Pro 2K高刷电竞显示器 电竞风拉满&#xff1a;作为猎鹰系列的一员&#xff0c;背部 “鹰翼图腾” 切割线搭配炎红…

STM32-时钟树

STM32-时钟树 时钟 时钟

基于SpringBoot+WebSocket的前后端连接,并接入文心一言大模型API

前言&#xff1a; 本片博客只讲述了操作的大致流程&#xff0c;具体实现步骤并不标准&#xff0c;请以参考为准。 本文前提&#xff1a;熟悉使用webSocket 如果大家还不了解什么是WebSocket&#xff0c;可以参考我的这篇博客&#xff1a; rWebSocket 详解&#xff1a;全双工…

StarRocks BE源码编译、CLion高亮跳转方法

阅读SR BE源码时&#xff0c;很多类的引用位置爆红找不到&#xff0c;或无法跳转过去&#xff0c;而自己的Linux机器往往缺乏各种C依赖库&#xff0c;配置安装比较麻烦&#xff0c;因此总体的思路是通过CLion远程连接SR社区已经安装完各种依赖库的Docker容器&#xff0c;进行编…

STM32 按键密码系统的实现

本次基于STM32F407开发板&#xff0c;来实现密码系统&#xff0c;输入四位密码&#xff0c;密码正确时LED1亮&#xff0c;密码错误时四个LED灯双闪。 LED双闪代码 简单的逻辑&#xff0c;让四个LED灯先亮然后再延时一会LED灯灭&#xff0c;循环4此实现双闪的效果。 按键密码的…

linux常用加固方式

目录 一.系统加固 二.ssh加固 三.换个隐蔽的端口 四.防火墙配置 五.用户权限管理 六.暴力破解防护 七.病毒防护 八.磁盘加密 九.双因素认证2FA 十.日志监控 十一.精简服务 一.系统加固 第一步&#xff1a;打好系统补丁 sudo apt update && sudo apt upgra…

hadoop==docker desktop搭建hadoop

hdfs map readuce yarn https://medium.com/guillermovc/setting-up-hadoop-with-docker-and-using-mapreduce-framework-c1cd125d4f7b 清理资源 docker-compose down docker system prune -f

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

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

Fullcalendar @fullcalendar/react 样式错乱丢失问题和导致页面卡顿崩溃问题

问题描述&#xff1a; 我使用 fullcalendar的react版本时&#xff0c;出现了一个诡异的问题&#xff0c;当我切换到 一个iframe页面时&#xff08;整个页面是一个iframe嵌入的&#xff09;&#xff0c;再切换回来日历的样式丢失了&#xff01;不仅丢失了样式还导致页面崩溃了&…

算法12(力扣739)-每日温度

1、问题 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0c;请在该位置用 0 来代替。 2、示例 &#…

STM32项目分享:智能厨房安全检测系统

目录 一、前言 二、项目简介 1.功能详解 2.主要器件 三、原理图设计 四、PCB硬件设计 PCB图 五、程序设计 六、实验效果 七、资料内容 项目分享 一、前言 项目成品图片&#xff1a; 哔哩哔哩视频链接&#xff1a; STM32智能厨房安全检测系统 &#xff08;资料分…

定时器按键tim_key模版

低优先级放在高优先级内势必是程序卡死 把高优先级放到低优先级内&#xff0c;会使程序卡死 可修改 Debuger调试方法 Pwm rcc #include "my_main.h" uint8_t led_sta0x10; char text[30]; void LED_Disp(uint8_t dsLED) {HAL_GPIO_WritePin(GPIOC,GPIO_PIN_All,GPI…

大模型-本地化部署调用--基于ollama+openWebUI+springBoot

大模型-本地化部署调用–基于ollamaopenWebUIspringBoot 前言 前段时间&#xff0c;啊&#xff0c;可能不是前段时间&#xff0c;过去的2024年吧&#xff0c;大模型这块的内容也是非常火的&#xff0c;各家巨头也开始卷大模型的研发。那么本人呢也在过去的一年中也是用到了一…

RV1126+FFMPEG推流项目源码

源码在我的gitee上面&#xff0c;感兴趣的可以自行了解 nullhttps://gitee.com/x-lan/rv126-ffmpeg-streaming-projecthttps://gitee.com/x-lan/rv126-ffmpeg-streaming-project

宏_wps_宏修改word中所有excel表格的格式_设置字体对齐格式_删除空行等

需求&#xff1a; 将word中所有excel表格的格式进行统一化&#xff0c;修改其中的数字类型为“宋体&#xff0c; 五号&#xff0c;右对齐&#xff0c; 不加粗&#xff0c;不倾斜”&#xff0c;其中的中文为“宋体&#xff0c; 五号&#xff0c; 不加粗&#xff0c;不倾斜” 数…

ServletOutputStream failed to write: Broken pipe

案发现场 问题&#xff1a; org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream failed to write: Broken pipe org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream …