9.12日考试总结

2024-06-11 13:32
文章标签 总结 考试 9.12

本文主要是介绍9.12日考试总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天花4个小时做了一套6道题,效果不是很理想。


前两题不说了,很简单。



第三题就是大坑了,给出一个字符串,从金字塔顶端向下一层一层地蛇形填充,字符串用完则重头再来,询问某一层一个字母出现了多少次。范围:字符串长度10^6,层数10^18(明明层数几万就可以把所有的非正确算法卡死完了,非要弄那么大)。

这个还是比较好想,首先确定蛇形是个幌子,不影响结果。对于一个询问,求出前面有多少个字母,然后就可以锁定这一行开始的字母是什么了,然后做一个除法,最后特判一下剩余的就行了。但是要注意,等比数列前N项和模字符串长度时,n*(n+1)/2在乘的时候会爆,需要将那个除以二放在n和n+1中是偶数的那里去除,然后两个边分别模了再乘,不然会溢出的。




第四题杀人游戏,N个人,每个人指认一个人,杀手不会指认同党,平民随意指认,计算最多有多少人是杀手,N在五十万以内。首先画成图,一个点若是杀手,则直接连边的点不能是杀手(差不多是个最大独立集)。

我考场上做的时候搞忘这种图的性质了,所以没弄出正解。每个点只有一个出边,说明每个连通块内最多只有一个环,然后枚举割掉环上任意相邻两边的两种情况,较大值就是这个连通块的解了。P.S. yly大蛤考完后把ZJOI2008骑士那道题的代码改了一下,把所有点权全部设为1,直接过了这道题orz。。




第五题:M栋宿舍楼,一共N天,每天有个人到入住到一个指定的宿舍楼,同时会举办一个派对,嘈杂度为该宿舍楼里的人数(包括他自己)。现一共有K次机会可以把任意一栋教学楼里的人轰走,问怎样安排使得嘈杂度之和最小。M<=100,N<=10^6,K<=500.

这种题一般二分或DP。二分不太好检验,就从DP入手吧。先明确顺序不重要,统计出每栋楼一共先后来了多少人就行了。

首先 f[i, j] 表示i个人,分成j部分产生的最小代价。然后再利用求得的f值做一次0~K背包即可。这个算法由两个DP构成,后半部分不会超时,前半部分就会TLE&MLE了。可以想到贪心的思路取而代之,尽量平均分,但是我考场上平均分这里细节没处理好,我想的是前面几部分每部分一样多,最后的余数自成一组,这个是不科学的。事实证明最好是可以分成若干组,使得每组之间的差值不超过1,而且这一定是可以做到的,至于有多少个是下取整,多少个是上取整,用古人解鸡兔同笼那种抬起一只脚的方法就行了。

谢天谢地后面的0~k背包数据范围设置不大。不然再加上队列优化就彻底麻烦啦。

#include<iostream>
#include<cstdio>
#include<cstring>
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
#define LL long long
const int MAXN = 1000010;
const LL INF = 1LL<<60;
int N, M, K;
LL f[505];
int cnt[505];LL arrange(int n0, int t0) { //n0个分为t0组if (n0 % t0 == 0) {return ((LL)t0) * (1 + n0/t0) * (n0/t0) / 2LL;}LL each = n0/t0, more = n0%t0;return more*(2+each)*(1+each)/2 + (t0-more)*(1+each)*each/2;
}void BackPack() {for (int i = 1; i<=M; ++i)for (int j = K; j>=0; --j) {LL mn = INF;for (int k = 0; k<=cnt[i] && k<=j; ++k)mn = Min(mn, f[j-k] + arrange(cnt[i], k+1));f[j] = mn;}
}int main()
{scanf("%d%d%d", &N, &M, &K);int t;for (int i = 1; i<=N; ++i){scanf("%d", &t);cnt[t] ++;}BackPack();cout << f[K] << '\n';return 0;
}


最后一题,给定一棵树,树上有若干关键点,求从树上每个点开始走完所有关键点的最短路径。N在五十万。

这题我考场上基本一眼看出正解,但是没时间了,早知道这题分值这么大我就先做这题了。。

正解给的是什么连接关键点的路径减去最长链上的路径什么的,比较巧妙。

我想的是从这题本身出发,强行上树DP。具体实现有点像K辆铲雪车问题和最长链问题的合集。

f[i,1]表示从i出发,走完i为根的子树中的所有关键点,最后回到i的最短路径。

f[i,0]表示从i出发,走完i为根的子树中的所有关键点,最后停在子树中的最短路径,同时come[i]记录这个值从哪个子树来的。

f[i,2]意义和f[i,0]类似,只不过是次短路径,切与f[i,0]来自不同的子节点。

g[i,1]和g[i,0],分别表示从i开始,走完其父亲边通向的所有关键点,最后是否返回i节点的最短路径。

转移的时候真的比较麻烦,方程也不是特别好描述。。特别是g数组的转移,一定要多考虑细节。

最后答案,对于每个i,取(f[i,0]+g[i,1])和(f[i,1]+g[i,0])之间的较小值即可。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
const int MAXN = 500010;void get(int &r) {char c; r = 0;do c=getchar(); while (c<'0'||c>'9');do r=r*10+c-'0',c=getchar(); while (c>='0'&&c<='9');
}struct Node {int to, d; Node*next;
}Edge[MAXN*2], *ecnt=Edge, *adj[MAXN];
void adde(int a, int b, int c) {(++ecnt)->to = b;ecnt->d = c;ecnt->next = adj[a];adj[a] = ecnt;
}
int N, K;LL f[MAXN][3], g[MAXN][2];
int come[MAXN];
bool must[MAXN];
bool need[MAXN], need1[MAXN];
int needn[MAXN];
int fa[MAXN], fal[MAXN];void predfs(int u)
{if (must[u])need1[u] = need[u] = 1;for (Node*p = adj[u]; p; p=p->next){if (p->to == fa[u]) continue;fa[p->to] = u;fal[p->to] = p->d;if (need1[fa[u]]) need1[u] = 1;predfs(p->to);if (need[p->to]) need[u] = 1;needn[u] += need[p->to];}
}void dfs1(int u)
{int mx1 = 0, mx2 = 0, t;for (Node*p = adj[u]; p; p=p->next){if (p->to == fa[u] || !need[p->to]) continue;dfs1(p->to);t = (p->d) - f[p->to][0] + f[p->to][1];if (t > mx1) mx2 = mx1, mx1 = t, come[u] = p->to;else if (t > mx2) mx2 = t;f[u][1] += f[p->to][1] + 2*p->d;}f[u][0] = f[u][1] - mx1;f[u][2] = f[u][1] - mx2;
}void dfs2(int u)
{need1[u] = need1[fa[u]] || (needn[fa[u]]-need[u])>0;if (need1[u]){g[u][1] = g[fa[u]][1] + f[fa[u]][1] - f[u][1];g[u][0] = g[fa[u]][0] + f[fa[u]][1] - f[u][1] - fal[u]*need[u];if (u==come[fa[u]])g[u][0] = Min(g[u][0], g[fa[u]][1] + f[fa[u]][2] - f[u][1] - fal[u]);elseg[u][0] = Min(g[u][0], g[fa[u]][1] + f[fa[u]][0] - (f[u][1]+fal[u])*need[u]);if (!need[u])g[u][1] += 2 * fal[u], g[u][0] += fal[u];}for (Node*p = adj[u]; p; p=p->next)if (p->to != fa[u])dfs2(p->to);
}int main()
{get(N), get(K);int a, b, c;for (int i = 1; i<N; ++i) {get(a), get(b), get(c);adde(a, b, c); adde(b, a, c);}for (int i = 1; i<=K; ++i)get(a), must[a] = 1;predfs(1);dfs1(1);dfs2(1);for (int i = 1; i<=N; ++i)cout << Min(g[i][0]+f[i][1], g[i][1]+f[i][0]) << '\n';return 0;
}



这篇关于9.12日考试总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1051308

相关文章

C# List.Sort四种重载总结

《C#List.Sort四种重载总结》本文详细分析了C#中List.Sort()方法的四种重载形式及其实现原理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录1. Sort方法的四种重载2. 具体使用- List.Sort();- IComparable

SpringBoot项目整合Netty启动失败的常见错误总结

《SpringBoot项目整合Netty启动失败的常见错误总结》本文总结了SpringBoot集成Netty时常见的8类问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、端口冲突问题1. Tomcat与Netty端口冲突二、主线程被阻塞问题1. Netty启动阻

SpringBoot整合Kafka启动失败的常见错误问题总结(推荐)

《SpringBoot整合Kafka启动失败的常见错误问题总结(推荐)》本文总结了SpringBoot项目整合Kafka启动失败的常见错误,包括Kafka服务器连接问题、序列化配置错误、依赖配置问题、... 目录一、Kafka服务器连接问题1. Kafka服务器无法连接2. 开发环境与生产环境网络不通二、序

python3中正则表达式处理函数用法总结

《python3中正则表达式处理函数用法总结》Python中的正则表达式是一个强大的文本处理工具,用于匹配、查找、替换等操作,在Python中正则表达式的操作主要通过内置的re模块来实现,这篇文章主要... 目录前言re.match函数re.search方法re.match 与 re.search的区别检索

Python版本与package版本兼容性检查方法总结

《Python版本与package版本兼容性检查方法总结》:本文主要介绍Python版本与package版本兼容性检查方法的相关资料,文中提供四种检查方法,分别是pip查询、conda管理、PyP... 目录引言为什么会出现兼容性问题方法一:用 pip 官方命令查询可用版本方法二:conda 管理包环境方法

pycharm跑python项目易出错的问题总结

《pycharm跑python项目易出错的问题总结》:本文主要介绍pycharm跑python项目易出错问题的相关资料,当你在PyCharm中运行Python程序时遇到报错,可以按照以下步骤进行排... 1. 一定不要在pycharm终端里面创建环境安装别人的项目子模块等,有可能出现的问题就是你不报错都安装

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

Spring 依赖注入与循环依赖总结

《Spring依赖注入与循环依赖总结》这篇文章给大家介绍Spring依赖注入与循环依赖总结篇,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. Spring 三级缓存解决循环依赖1. 创建UserService原始对象2. 将原始对象包装成工

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

在Java中实现线程之间的数据共享的几种方式总结

《在Java中实现线程之间的数据共享的几种方式总结》在Java中实现线程间数据共享是并发编程的核心需求,但需要谨慎处理同步问题以避免竞态条件,本文通过代码示例给大家介绍了几种主要实现方式及其最佳实践,... 目录1. 共享变量与同步机制2. 轻量级通信机制3. 线程安全容器4. 线程局部变量(ThreadL