25年CCPC福建邀请赛补题

写在前面

笔者五月二十四日要参加26年CC南昌邀请赛,为练题拉了八套前两年的CC邀请赛铜牌题及以下,计划在比赛前把这些题做完并补题,目前是第一篇,25CCPC福建邀请赛,四题铜六题银,自估难度M<G<K<J,M秒过,G是能写但是码的时候有很多边界问题,最后还需要一个前缀和优化,因为太长时间没写题了,所有这道题也不顺利,K题是一打眼就没什么思路,看完题解理解了,但是还是不会写,J看完题解也不是很理解,不会做,这场计划补一下G、K、J

G

题面:

**题意解释:**这个e不重要,可以看到只需要加减就行了。题目要求给定区间的第一天,然后算一直到区间最后一天最大收益,每一次都是独立计算

**思路:**很明显,这个需要找的是连续非递减序列,然后用序列中的最后一个减去第一个,一直这样算直到序列最后一天,就是答案

如果纯暴力时间复杂度是O(n*m),会t,所以需要用一个前缀和来优化上升序列的差值,而且还要注意到收益需要加上第一天的鸡债

前缀和计算上升序列差值就是,使用一个数组存max(0,下一个数减去上一个数的差),然后用前缀和存所有的差值之和,这样就存下了任意一段序列的上升段最后一个减去第一个

代码:

cpp 复制代码
void solve()
{
	ll n,m;
	cin>>n>>m;
	vector<ll>a(n+1);
	for(int i=1;i<=n;i++) cin>>a[i];
	ll k;
	cin>>k;
	vector<ll>temp(n+1);
	temp[0]=0;
	a[0]=0;
	for(int i=1;i<=n;i++)
	{
		temp[i]=max(ll(0),a[i]-a[i-1]);
	}
	vector<ll>pre(n+1);
	pre[0]=0;
	for(int i=1;i<=n;i++)
	{
		pre[i]=pre[i-1]+temp[i];
	}
	while(m--)
	{
		ll s,t;
		cin>>s>>t;
		cout<<pre[t]-pre[s]+k<<endl;
	}
}

K

题面:

**题意解释:**题意非常清晰,就是告诉你有一棵树,这棵树的边权就是两个点权相加,然后给定n-1条边权,但是不告诉具体点权,然后问有没有一种情况满足这些所有边权

**思路:**这个题我初步看是半点思路都没有的,根本想不到怎么做,然后看了题解,又理解了挺长时间,现在理解了。

可以设根节点点权为x,因为每个点都会直接或间接和根节点相连,所以每个点点权都可以用x表示,有可能是一个数+x,也有可能是一个数-x,这个怎么证明呢?当一个点与x直接相连时,肯定是w-x,然后另一个点与这个点相连的话,它就变成w1-(w-x),即w1-w+x,因为点权>0,所以可以求出x的范围是(w-w1)的最小值到w的最大值

**写一个笔者卡住的点:**我以为n-1条边没有把树定死,但是树的性质决定它只有n-1条边, 所以输入已经把树定死了,不需要担心有的边没给定边权,也不需要用根节点作为基数

如果这样这道题的难度就降低了,使用邻接表记录边权,然后DFS遍历每一个点,记录当前这个点相对x的正负和常数项,这样取max和min就得到结果了

代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

struct edge
{
	ll end;
	ll w;
};

vector<edge>vec[200005];
ll minNum,maxNum;
vector<ll>coffe(200005),off(200005);
vector<bool>st(200005);

void dfs(ll cnt,ll fa,ll c,ll o)
{
	st[cnt]=true;
	coffe[cnt]=c;
	off[cnt]=o;
	for(auto &t:vec[cnt])
	{
		ll u=t.end;
		ll w=t.w;
		if(u==fa) continue;
		ll nc=w-c;
		ll no=-o;
		dfs(u,cnt,nc,no);
	}
}

void solve()
{
	ll n;
	cin>>n;
	for(int i=0;i<n-1;i++)
	{
		ll u,v,w;
		cin>>u>>v>>w;
		vec[u].push_back({v,w});
		vec[v].push_back({u,w});
	}
	dfs(1,-1,0,1);
	ll L=-1e18;
	ll R=1e18;
	for(int i=1;i<=n;i++)
	{
		if(off[i]==1)
		{
			L=max(L,-coffe[i]+1);
		}
		else 
		{
			R=min(R,coffe[i]-1);
		}
	}
	if(R<L) 
	{
		cout<<"NO"<<endl;
		return;
	}
	ll x=L;
	cout<<"YES"<<endl;
	for(int i=1;i<=n;i++)
	{
		cout<<coffe[i]+off[i]*x<<" ";
	}
	cout<<endl;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	ll t=1;
	//cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

J

题面:

**题意:**给定一个数,可以让他加上它的一个没用过的正约数,问如何在100次操作内加成一个完全平方数

**思路:**这道题题意很好理解,但是我做的时候是没什么思路的,值得高兴的是我两个队友似乎都会做。首先先看是不是已经满足了完全平方,如果满足就输出0;如果不满足再构造。

构造的时候要考虑什么方法是最简单的,题目没有要求变成最小的完全平方数,所以任意一个完全平方数都可以,我们可以试试二进制打法

构造成2^(2*i)的形式,这样的二进制形式就是1后跟着偶数个0,想将一个随机的数加成这样,可以每一次都加最右边的1后跟若干0的数,毫无疑问这个数必定是约数且不会重复,证明一下:从二进制拆一个最右边的1和后边的0出来,然后剩下的是他左边离他最近的1和后边一堆0,具体形式就是101011110000拆成101011100000+10000,左边这个长的肯定是右边这个的倍数,所以整个也是倍数。不重复是因为随着每一次加最右边的1,这样1会不断进位,1会越来越靠左且越来越少,所以x只会越来越大,所以这样可以得到结果

但是实测的时候,如果先判断是不是完全平方数,会超时,所以直接通用一种构造即可

代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

ll fun(ll t)
{
	ll sum=1;
	while(t--) sum*=2;
	return sum;
}

ll lowbit(ll x)
{
	return x & -x;
}

void solve()
{
	ll n;
	cin>>n;
	vector<ll>ans;
	while(true)
	{
		ans.push_back(lowbit(n));
		n+=lowbit(n);
		if(n==lowbit(n)) break;
	}
	ll c=0;
	ll temp=n;
	while(n!=0)
	{
		n/=2;
		c++;
	}
	if(c%2==0)
	{
		cout<<ans.size()+1<<endl;
		for(int i=0;i<ans.size();i++) cout<<ans[i]<<" ";
		cout<<temp<<endl;
	}
	else
	{
		cout<<ans.size()<<endl;
		for(int i=0;i<ans.size();i++) cout<<ans[i]<<" ";
		cout<<endl;
	}
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	ll t=1;
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

篇末总结

其实这场比赛拿铜牌难度不大,只不过我太长时间没写题,一个基础的二进制、DFS都写不明白了,接下来再做25年郑州邀请赛

相关推荐
Slow菜鸟1 小时前
Skill 学习篇(十)| 编排框架 · 五大编排框架 · 全方位决策指南
学习
Raink老师1 小时前
用100道题拿下你的算法面试(链表篇-4):合并 K 个有序链表
算法·链表·面试
倒霉熊dd1 小时前
Python学习(第一部分 语法与数据结构/核心基础)
大数据·python·学习·pip
Liangwei Lin2 小时前
LeetCode 20. 有效的括号
算法
星夜夏空992 小时前
STM32单片机学习(3)——前置知识学习
stm32·单片机·学习
IronMurphy2 小时前
【算法四十四】322. 零钱兑换
算法
凯瑟琳.奥古斯特2 小时前
力扣2760 C++滑动窗口解法
数据结构·c++·算法·leetcode·职场和发展
Hesionberger2 小时前
LeetCode96: 不同的二叉搜索树(多解)
算法
_深海凉_2 小时前
LeetCode热题100-不同路径
算法·leetcode·职场和发展