牛客编程巅峰赛S2赛季第2场题解与参考代码
比赛链接:
初级场A题 热心的牛牛:
不妨设牛牛获得x枚糖果,那么牛牛的朋友每人需要至少获得x+1枚糖果。那么这种情况下需要的总糖果数为x+n(x+1),这个总数需要小于等于k。因此有x+n(x+1)<=k。整理得到(1+n)x+n<=k,合法的x值满足x<=(k-n)/(n+1),因此输出该式下取整就是答案。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 返回牛牛能吃到的最多糖果数
* @param n long长整型
* @param k long长整型
* @return long长整型
*/
long long Maximumcandies(long long n, long long k) {
return (k-n)/(n+1);
}
}; 初级场B题&高级场A题 牛牛切木棒:
这是比较经典的题目,使用斐波那契数列作为边长,可以使得任意三个数字不能作为一个三角形的边长。从小到大使用斐波那契数列的各项,就可以将木棒拆成若干个小木棒,任意三条木棒不能构成三角形。
class Solution {
public:
/**
*
* @param a long长整型 木棒的长度
* @return int整型
*/
long long f[100];
int stick(long long a) {
f[1]=1;
f[2]=1;
for(int i=3;f[i-1]<=1e18;++i){
f[i]=f[i-1]+f[i-2];
}
for(int i=1;;++i){
if (a<f[i]) return i-1;
a-=f[i];
}
}
}; 根据完全k叉数的性质可以推导出,或者可以观察出bfs序为i(i>0)的点,其父结点在bfs序中的编号为(i-1)/k。利用这个性质扫描一遍即可完成统计。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param k int整型 表示完全k叉树的叉数k
* @param a int整型vector 表示这棵完全k叉树的Bfs遍历序列的结点编号
* @return long长整型
*/
long long tree2(int k, vector<int>& a) {
long long ans=0;
for(int i=1;i<a.size();++i) ans+=a[i]^a[(i-1)/k];
return ans;
}
}; 高级赛C题 数据分析:
这题我用了稍微复杂的方法,当做是抛砖引玉提供了另一种思路。思路大致是,(假设题目给定的输入是数组numbers)按照numbers中的数字大小从小到大考虑并维护答案。一开始不妨先当做numbers中所有数字都被拿掉了,然后按数字从小到大的顺序逐个放回numbers中的数字,那么某一时刻,numbers中只会存在一部分元素,在numbers中形成若干个连续段。假设现在从小到大考虑完的元素是numbers[i],那么该时刻numbers中只会存在所有<=numbers[i]的所有数,之后考虑放入将numbers中所有数排序后的后继x,那么放入x后,可能会将其左右的两段连接成一个连续段。注意到目前放入numbers中的数都不大于x,因此当前numbers中存在的数形成的任何一个子区间最大值都不会大于x。考虑x所在的那么连续段,不妨设这个连续段的长度为l,那么x可以更新长度小于等于l的区间的区间最大值的答案,也就是说长度小于等于l的区间的区间最大值的最小值小于等于x。因此从小到大插入numbers中的元素,可以得到若干个上述ans[1..l]<=x的信息。最后利用这些信息就可以计算出ans。插入元素与合并段的代码具体实现可以采用并查集,或者也可以直接采用类似链表的方式维护。
struct nod{
int v,x;
inline bool operator <(const nod &a)const{
return v<a.v;
}
};
class Solution {
public:
/**
* 找到所有长度子数组中最大值的最小值
* @param numbers int整型vector 牛牛给出的数据
* @return int整型vector
*/
int f[110000],l[110000],r[110000];
nod g[110000];
int ans[110000];
bool b[110000],hans[110000];
int father(int x){
if (f[x]!=x) f[x]=father(f[x]);
return f[x];
}
void merge(int x,int y){
int fx=father(x);
int fy=father(y);
if (fx!=fy){
f[fx]=fy;
if (l[fx]<l[fy]) l[fy]=l[fx];
if (r[fx]>r[fy]) r[fy]=r[fx];
}
}
vector<int> getMinimums(vector<int>& numbers) {
// write code here
//if (numbers.size()==1) return numbers;
int n=numbers.size();
for(int i=1;i<=n;++i){
f[i]=l[i]=r[i]=i;
g[i]=(nod){numbers[i-1],i};
b[i]=hans[i]=0;
}
b[0]=b[n+1]=0;
sort(g+1,g+n+1);
for(int i=1;i<=n;++i){
int &x=g[i].x;
b[x]=1;
if (b[x-1]) merge(x,x-1);
if (b[x+1]) merge(x,x+1);
int fx=father(x);
int len=r[fx]-l[fx]+1;
if (!hans[len]){
hans[len]=1;
ans[len]=g[i].v;
}
}
for(int i=n-1;i>=1;--i){
if (!hans[i]) ans[i]=ans[i+1];
if (ans[i+1]<ans[i]) ans[i]=ans[i+1];
}
vector<int> v;
for(int i=1;i<=n;++i) v.push_back(ans[i]);
return v;
}
};