牛客练习赛131(dp,dfs,bfs,线段树维护等差数列)

文章目录

  • 牛客练习赛131(dp,dfs,bfs,线段树维护等差数列)
    • A. 小H学语文
    • B. 小H学数学(dp、偏移值)
    • C. 小H学生物(DFS、树上两点间路径的距离)
    • D. 小H学历史(BFS)
    • E. 小H学物理 (线段树±区间等差数列)

牛客练习赛131(dp,dfs,bfs,线段树维护等差数列)


整场题意都要靠和出题人心心相印才行,(lll¬ω¬)

F不会,PASS


A. 小H学语文

题意:

n n n 个木板中选择 m m m 个,定义 V = m 2 ∗ h m i n V = m^2 * h_{min} V=m2hmin,输出一个方案,令 V V V 最大。其中, m m m 表示木板的个数, h m i n h_{min} hmin 表示选择木板的最小值。

思路:

按木板长度排序,每次选前 i i i 大个木板,作为方案,取最大的 V V V

code:

#include<bits/stdc++.h>using namespace std;const int maxn = 2e5 + 10;pair<int, int> a[maxn];int main(){int n;cin >> n;int x;for(int i = 1; i <= n; i++){cin >> x;a[i] = {x, i};}sort(a+1, a+1+n);long long mx = 0, pos = 0;for(int i = n; i >= 1; i--){long long tmp = 1ll * (n - i + 1) * (n - i + 1) * a[i].first;if(tmp > mx){mx = tmp;pos = i;}}vector<int> res;for(int i = pos; i <= n; i++) res.push_back(a[i].second);sort(res.begin(), res.end());cout << res.size() << endl;for(auto x : res) cout << x << " ";cout << endl;return 0;
}

B. 小H学数学(dp、偏移值)

题意:

y + 1 y+1 y+1个人,每个人的两个手,手指健全。对于每个人,可以用两个手表示一个 [ 1 , 10 ] [1, 10] [1,10] 的数,也可以用两个手各表示一个 [ 1 , 5 ] [1, 5] [1,5] 的数。

问:这些人有多少种方案,使得他们表示的数字通过加减计算出 x x x。(任意一个同学左右手表示的数不同或者计算时需要的操作符不同视为不同的方案)

思路:

先考虑一个人,表示 [ 1 , 10 ] [1,10] [1,10] 之间的数。令 V [ x ] V[x] V[x] 表示一个人有多少种方案可以构成 x x x,直接暴力枚举维护出 V V V 数组。

再考虑多个人,令 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示 i i i 个人,构成 j j j 的方案数。 d p [ i ] [ j ] = ∑ x d p [ i − 1 ] [ j ± x ] + V [ x ] , x ∈ V k e y dp[i][j] = \sum_x dp[i-1][j±x] + V[x], x \in V_{key} dp[i][j]=xdp[i1][j±x]+V[x],xVkey

最后,因为 x 可能出现负数,注意设置偏移值。

code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;const int maxn = 2e3 + 10;
const int M = 1e3;
const ll mod = 1e9 + 7;ll dp[105][maxn];map<int, int> v;int main(){// for(int i = 1; i <= 5; i++){for(int j = 1; j <= 5; j++){int a = i + j;int b = i - j;
//    		printf("(%d,%d) = %d, %d\n", i, j, a, b);v[a]++;v[b]++;}}for(int i = 1; i <= 10; i++) v[i]++;	//	for(auto i : v) cout << i.first << " " << i.second << endl;int x, y;cin >> x >> y;dp[0][M+0] = 1;for(int i = 1; i <= y+1; i++){for(int j = -1000; j <= 1000; j++){for(auto _ : v){ll num = _.first, cnt = _.second;if(j - num >= -1000 && j - num <= 1000){dp[i][M+j] = (dp[i][M+j] + dp[i-1][M+j-num] * cnt % mod) % mod;}if(j + num >= -1000 && j + num <= 1000){dp[i][M+j] = (dp[i][M+j] + dp[i-1][M+j+num] * cnt % mod) % mod;}}}}cout << dp[y+1][x+M] << endl;return 0;
}

C. 小H学生物(DFS、树上两点间路径的距离)

题意:

给一棵树 T T T 和一个序列 A A A,树上每条边都有一个二进制边权,序列 A A A 中每个元素对应树上一个节点。

设:

  • 在序列 A A A中,设点对 ( i , j ) (i, j) (i,j)的距离为 ∣ j − i ∣ |j - i| ji
  • 对于点对 ( i , j ) (i, j) (i,j),其 D D D 值 = 在树 T T T上,节点 A i A_i Ai 到节点 A j A_j Aj 的边权的异或和。

求:序列 A A A 中,所有满足距离大于 1 1 1 的点对的 D D D 值的异或和。

思路:

对于异或的两个知识点:

  • X ^ X = 0
  • X ^ 0 = X

对于树上任意两点的简单路径的一个知识点:

  • 在树上, d i s t ( u , v ) = d e e p ( u ) + d e e p ( v ) − d e e p ( L C A ( u , v ) ) ∗ 2 dist(u, v) = deep(u) + deep(v) - deep(LCA(u,v)) * 2 dist(u,v)=deep(u)+deep(v)deep(LCA(u,v))2,其中 d e e p ( x ) deep(x) deep(x) 表示x的深度, L C A ( u , v ) LCA(u,v) LCA(u,v) 表示 u 和 v的最近公共祖先。(原理自行百度即可)

类比上述知识点,推理得到:任意两点之间的边权异或和 d u , v = d 1 , u ⨁ d 1 , v d_{u,v} = d_{1,u} \bigoplus d_{1, v} du,v=d1,ud1,v,其中 d u , v d_{u,v} du,v 表示 u 到 v 的简单路径异或和,一遍DFS即可维护出全部的 d 1 , x d_{1, x} d1,x


设序列 A = {5, 4, 3, 6},则 r e s = d 5 , 3 ⨁ d 5 , 6 ⨁ d 4 , 6 = ( d 1 , 5 ⨁ d 1 , 3 ) ⨁ ( d 1 , 5 ⨁ d 1 , 6 ) ⨁ ( d 1 , 4 ⨁ d 1 , 6 ) res = d_{5, 3} \bigoplus d_{5, 6} \bigoplus d_{4, 6} = (d_{1, 5} \bigoplus d_{1, 3}) \bigoplus (d_{1, 5} \bigoplus d_{1, 6}) \bigoplus (d_{1, 4} \bigoplus d_{1, 6}) res=d5,3d5,6d4,6=(d1,5d1,3)(d1,5d1,6)(d1,4d1,6)

观察上述,式子,可以发现,每个元素对 res 的贡献,对它所在学列A中的位置有关。

手搓两个样例,对 |A| 是奇偶的情况分类讨论即可总结出。

code:

#include<bits/stdc++.h>using namespace std;const int maxn = 1e5 + 5;int a[maxn], in[maxn];
vector<pair<int, bitset<100>>> mp[maxn];bitset<100> d[maxn]; // d[i] = i 到 root 的异或值 void dfs(int u){for(auto item : mp[u]){d[item.first] = d[u] ^ item.second;dfs(item.first);}
}int main(){int n, m, l;cin >> n >> m >> l;int u, v; char c;    for(int i = 2; i <= n; i++){cin >> u >> v;	bitset<100> tmp;for(int j = 0; j < l; j++){cin >> c;tmp[j] = (c == '1' ? 1 : 0);}mp[u].push_back({v, tmp});in[v]++;}for(int i = 1; i <= m; i++) cin >> a[i];int root = 1;for(int i = 1; i <= n; i++) if(in[i] == 0) root = i;dfs(root);bitset<100> res;if(m&1) res = d[a[1]] ^ d[a[m]];else{for(int i = 2; i < m; i++){res = res ^ d[a[i]];}}for(int i = 0 ; i < l; i++) cout << res[i];cout << endl;return 0;
}

D. 小H学历史(BFS)

题意:

有一棵树,每个节点的点有一个标记值,A 、B 或者 Z。A 和 B 的节点可以攻击 Z 的结点,把Z变为和自己一样的标记。并且,树中度为一的结点一定为 A 或 B。

若干次进攻后,树上没有标记为 Z的结点,求||A| - |B|| 的最小值。(标记为 A 的节点数 - 标记为 b 的节点数的绝对值的最小值)

思路:

先分别求,标记为 A 的结点的最大值MX_A 和标记为 B 的结点的最大值MX_B。(从标记为 A 的结点开始BFS,遍历所有的结点,即可求出MX_A,MX_B同理)

再求,标记为 A 的结点的最小值MN_A = n - MX_B 和标记为 B 的结点的最小值MN_B = n - MX_A。

现考虑所有情况,设 MN_A <= MN_B:

  1. MN_A = 0,则 res = n
  2. MN_A != 0 ,因为 MN_A <= MN_B,所以 MN_A <= n /2,
    1. 如果这时 MX_A >= n / 2,A 的数量一定可以等于 n/2,res = n % 2
    2. 如果这时 MX_A < n / 2,A 的数量一定小于 n/2,res = MN_B - MX_A,即所有可变为A 的 Z 都变为A。

补充两个帮助例子,用作解释为什么求 MX_A 和 MN_A:

  • 自由的 Z,如下图所示,这时的 Z 可为 A 也可以为 B。
    在这里插入图片描述

  • 不自由的 Z,这时 Z 只能为 A。
    在这里插入图片描述

code:

#include<bits/stdc++.h>using namespace std;const int maxn = 1e5 + 5;vector<int> mp[maxn];
char c[maxn];
int vis[maxn];int bfs(int n, char flag){queue<int> qu;for(int i = 1; i <= n; i++){if(c[i] == flag){qu.push(i);vis[i] = 1;} else vis[i] = 0;}int mx = 0;while(!qu.empty()){int u = qu.front();qu.pop();mx++;for(auto v : mp[u]){if(vis[v] == 1) continue;if(c[v] == flag || c[v] == 'Z'){qu.push(v);vis[v] = 1;}}}return mx;
}int main(){int n;cin >> n;for(int i = 1; i <= n; i++) cin >> c[i];int x, y;for(int i = 2; i <= n; i++){cin >> x >> y;mp[x].push_back(y);mp[y].push_back(x);}int mx_A = bfs(n, 'A'), mx_B = bfs(n, 'B');int mn_A = n - mx_B, mn_B = n - mx_A;if(mn_A > mn_B) swap(mn_A, mn_B), swap(mx_A, mx_B);if(mn_A == 0) cout << n << endl;else if(mx_A >= n / 2) cout << n % 2 << endl;else cout << n - mx_A - mx_A << endl;return 0;
}

E. 小H学物理 (线段树±区间等差数列)

思路:

维护λ颗线段树,每次修改操作,维护两个值。一个是区间整体±的值value,另一个为区间被操作的次数cnt。

更具体的,如下图所示。如果对区间 [1, 6] 进行一次操作,划分为两个子区间 [1, 3] 和 [4, 6]。

在子区间 [1, 3] 上,等价于区间整体 + x,再减去一个递减序列(0, 1,2)。

在子区间 [4, 6] 上,等价于区间整体 + y,再减去一个递减序列(0, 1,2)。

类比到线段树上,一个结点的两个孩子结点的大小是一定的,对一个结点的操作可以等价为上述的分裂操作。

其中,比较重要的是,计算出 h 的值,左孩子区间长度 * 公差 d,即可求出右孩子的 y。

在这里插入图片描述

code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;const int maxn = 1e5 + 5;typedef struct Node{ll value;ll lazy;ll cnt;
} node;node tree[10][maxn * 4];void pushdown(int tno, int root, int l, int r){if(tree[tno][root].lazy || tree[tno][root].cnt){ll mid = l + r >> 1, len_l = mid - l + 1, len_r = r - mid;tree[tno][root<<1].value += tree[tno][root].lazy * len_l - tree[tno][root].cnt * len_l * (len_l - 1) / 2;tree[tno][root<<1].lazy += tree[tno][root].lazy;tree[tno][root<<1].cnt += tree[tno][root].cnt;ll new_lazy = tree[tno][root].lazy - len_l * tree[tno][root].cnt;tree[tno][root<<1|1].value += new_lazy * len_r - tree[tno][root].cnt * len_r * (len_r - 1) / 2;tree[tno][root<<1|1].lazy += new_lazy;tree[tno][root<<1|1].cnt += tree[tno][root].cnt;tree[tno][root].lazy = tree[tno][root].cnt = 0;}
}void update(int tno, int root, int l, int r, int L, int R, ll value){if(L <= l && r <= R){ll op = (value > 0 ? -1 : 1);tree[tno][root].value += 1ll * (value + op *  (l - L)) * (r - l + 1) + op *  (r - l + 1) * (r - l) / 2;tree[tno][root].lazy += (value + op * (l - L));tree[tno][root].cnt += (value > 0 ? 1 : -1); // cnt 表示 sum(0 -1 -2 -3 ...),value + 则要 +1次 return;}pushdown(tno, root, l, r);int mid = l + r >> 1;if(L <= mid) update(tno, root<<1, l, mid, L, R, value);if(R > mid) update(tno, root<<1|1, mid+1, r, L, R, value);tree[tno][root].value = tree[tno][root<<1].value + tree[tno][root<<1|1].value;
}long long query(int tno, int root, int l, int r, int L, int R){if(L <= l && r <= R) return tree[tno][root].value;pushdown(tno, root, l, r);long long res = 0, mid = l + r >> 1;if(L <= mid) res += query(tno, root<<1, l, mid, L, R);if(R > mid) res += query(tno, root<<1|1, mid+1, r, L, R);tree[tno][root].value = tree[tno][root<<1].value + tree[tno][root<<1|1].value;return res;
}int main(){int n, q, l;cin >> q >> n >> l;int nn = n;n = n / l + 1;while(q--){int op, x, y;cin >> op >> x >> y;if(op == 0) {int tno = x % l, L = x / l + 1;update(tno, 1, 1, n, L, min(L + abs(y) - 1, n), y);
// 			for(int i = 1; i <= nn; i++) 
// 				cout << query(i%l, 1, 1, n, i / l + 1, i / l + 1) << " ";
// 			cout << endl;			}else{long long res = 0;if(y - x < 5 * l){for(int i = x; i <= y; i++){res += query(i % l, 1, 1, n, i / l + 1, i / l + 1);}}else{while(x % l != 0){res += query(x % l, 1, 1, n, x / l + 1, x / l + 1);x++;}while(1){res += query(y % l, 1, 1, n, y / l + 1, y / l + 1);if(y % l == 0) break;else y--;}int s = x / l + 1, e = y / l + 1 - 1; // y 所在的块已经算过了,所以-1 for(int i = 0; i < l; i++){res += query(i, 1, 1, n, s, e);}}cout << res << endl;}}return 0;
}

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

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

相关文章

干货分享篇:Air780EP的硬件设计原理全解析(上)

一、绪论 Air780EP是一款基于移芯EC718P平台设计的LTE Cat 1无线通信模组。支持FDD-LTE/TDD-LTE的4G远距离无线传输技术。另外&#xff0c;模组提供了USB/UART/I2C等通用接口满足IoT行业的各种应用诉求。 二、综述 2.1 型号信息 表格 1&#xff1a;模块型号列表 2.2 主要性能…

Python将Word文档转为PDF

将word转pdf&#xff0c;只能使用办公工具&#xff0c;但是这些工具大都是收费。因此想用python 将word转pdf,发现很好用特此记录下。方法一&#xff1a;使用docx2pdf模块将docx文件转为pdf 要实现这样的功能&#xff0c;需要用到的就是 docx2pdf 这个python第三方库。对于doc…

无惧任天堂的法律威胁:Switch模拟器Ryujinx v1.2.72版发布

此前任天堂向多个提供 Nintendo Switch 模拟器项目发送律师函甚至直接起诉&#xff0c;要求这些项目立即停止更新、删除以及向任天堂提供经济赔偿。其中 Ryujinx 项目已经在 2024 年 10 月 1 日因任天堂的法律威胁而放弃项目&#xff0c;不过很快就有分叉版本出现&#xff0c;这…

JavaWeb——Web入门(6/9)-HTTP协议:协议解析(客户端的 HTTP 协议解析、服务端的 HTTP 协议解析、Web服务器的作用)

目录 概述 客户端的 HTTP 协议解析 服务端的 HTTP 协议解析 Web服务器的作用 概述 了解完 HTTP 协议的请求数据格式以及响应数据格式之后&#xff0c;接下来我们来讲了解 HTTP 协议的解析。 HTTP 协议的解析分为客户端和服务端两个部分&#xff0c;客户端浏览器中内置了解…

操作系统-实验报告单(2)

目录 1 实验目标 2 实验工具 3 实验内容、实验步骤及实验结果 一、自定义操作系统并启动 1. 最简单操作系统的编写并生成镜像文件 2.虚拟机启动操作系统 【思考题&#xff1a;1、仔细阅读helloos.nas&#xff0c;结合操作系统启动过程尝试分析它的作用&#xff1b;2、若…

城镇住房保障:SpringBoot系统优化技巧

3系统分析 3.1可行性分析 通过对本城镇保障性住房管理系统实行的目的初步调查和分析&#xff0c;提出可行性方案并对其一一进行论证。我们在这里主要从技术可行性、经济可行性、操作可行性等方面进行分析。 3.1.1技术可行性 本城镇保障性住房管理系统采用SSM框架&#xff0c;JA…

FlyMcu串口下载STLink Utility

1、FlyMcu FlyMcu串口下载&#xff0c;同STC-ISP&#xff08;51单片机下载&#xff09;。 使用步骤&#xff1a; 1、STM32的USART1通过串口转usb连接到电脑 2、通过keil生成Hex、bin文件 生成bin、hex文件可参考 keil生成bin文件&#xff08;简单&#xff09;-CSDN博客 创建…

aws(学习笔记第十课) 对AWS的EBS如何备份(snapshot)以及使用snapshot恢复数据,AWS实例存储

aws(学习笔记第十课) 对AWS的EBS如何备份&#xff08;snapshot&#xff09;以及使用snapshot&#xff0c;AWS实例存储 学习内容&#xff1a; 对AWS的EBS如何备份AWS实例存储EBS和实例存储的不足 1. 对AWS的EBS如何备份&#xff08;snapshot&#xff09;以及使用snapshot恢复数…

论文2—《基于柔顺控制的智能神经导航手术机器人系统设计》文献阅读分析报告

论文报告&#xff1a;基于卷积神经网络的手术机器人控制系统设计 摘要 本研究针对机器人辅助微创手术中定向障碍和缺乏导航信息的问题&#xff0c;设计了一种智能控制导航手术机器人系统。该系统采用可靠和安全的定位技术、7自由度机械臂以及避免关节角度限制的逆运动学控制策…

《数据结构与算法》二叉树基础OJ练习

二叉树的基础知识详见&#xff1a;《数据结构与算法》二叉树-CSDN博客 1 单值二叉树 思路 我们把树分成当前树&#xff08;用根和左孩子还有右孩子进行比较&#xff0c;如果左孩子或者右孩子为空那就不比了&#xff0c;如果左右孩子或者其中一个存在就比较&#xff0c;相等就是…

栈和队列(C 语言)

目录 一、栈1. 栈的概念2. 栈的结构3. 栈的实现思路4. 栈的实现代码 二、队列1. 队列的概念2. 队列的结构3. 队列的实现思路4. 队列的实现代码5. 循环队列 一、栈 1. 栈的概念 栈是一种特殊的线性表&#xff0c;只允许在固定的一端进行插入和删除操作&#xff0c;该端被称为栈…

自动化测试工具Ranorex Studio(二十五)-库的拆分

默认地&#xff0c;每一个Ranorex Studio项目包含一个对象库文件&#xff0c;这个文件自动用在每一个新创建的录制中。你可以在一个单独的库文件中管理一个测试套件项目中所有的UI元素&#xff0c;但是在一个自动化测试项目中多个对象库的存在还是有一些原因的&#xff1a; .测…

Centos下安装Maven(无坑版)

Linux 安装 Maven Maven 压缩包下载与解压 华为云下载源&#xff0c;自行选择版本 下面的示例使用的是 3.8.1 版本 wget https://repo.huaweicloud.com/apache/maven/maven-3/3.8.1/binaries/apache-maven-3.8.1-bin.tar.gz解压 tar -zxvf apache-maven-3.8.1-bin.tar.gz移…

99、Python并发编程:多线程的问题、临界资源以及同步机制

引言 多线程技术的引入&#xff0c;可以帮助我们实现并发编程&#xff0c;一方面可以充分利用CPU计算资源&#xff0c;另一方面&#xff0c;可以在用户体验上带来极大的改善。但是&#xff0c;多线程技术也存在一些问题。本文就来简单聊一下多线程引入导致的问题&#xff0c;以…

jmeter常用配置元件介绍总结之取样器

系列文章目录 1.windows、linux安装jmeter及设置中文显示 2.jmeter常用配置元件介绍总结之安装插件 3.jmeter常用配置元件介绍总结之取样器 jmeter常用配置元件介绍总结之取样器 2.取样器2.1.HTTP请求2.2.Debug Sampler2.3.JSR223 Sampler2.4.JDBC Connection Configuration和J…

Python练习11

Python日常练习 题目&#xff1a; 编写一个石头剪刀布游戏&#xff0c;该程序要求完成如下功能&#xff1a; (1) 显示游戏规则&#xff0c;提醒用户输入一个1-3的整数或者直接回车。 用户输入回车时游戏结束。 用户输入不合法&#xff08;包括输入的…

什么是欧拉角和四元数

涉及机器人调度工作的一些基本概念整理理解 目录 什么是欧拉角和四元数 &#xff1f;相关工具网站相关工具代码 什么是欧拉角和四元数 &#xff1f; 这里画了一张图&#xff0c;简明方便理解&#xff1a; 欧拉角 (Euler Angles) 是一种描述物体在三维空间旋转姿态的方法&…

关于几种卷积

1*1卷积 分组卷积&深度可分离卷积 空洞卷积、膨胀卷积 转置卷积 https://zhuanlan.zhihu.com/p/80041030 https://yinguobing.com/separable-convolution/#fn2 11的卷积可以理解为对通道进行加权&#xff0c;对于一个通道来说&#xff0c;每个像素点加权是一样的&am…

std::copy

std::copy 是 C 标准库中的一个算法&#xff0c;用于将一个序列中的元素复制到另一个位置。这个算法定义在 <algorithm> 头文件中。 --- 函数原型 std::copy 有几个不同的重载版本&#xff0c;但以下是最常用的两个&#xff1a; template <class InputIterator, c…