Codeforces Round 982 (Div. 2) 题解(A-D)


Codeforces Round 982 (Div. 2)

A

思路

因为图形可以重叠, 所以答案就是最长的长和最长的宽组成的矩形周长.

code

void func(void)
{
	int n;
	cin >> n;
	int l = 0,r = 0;
	while(n--)
	{
		int x,y;
		cin >> x >> y;
		l = max(l,x), r = max(r,y);
	}
	cout << 2*l+2*r << '\n';
}

B

思路

因为 n2000, 所以可以用 O(n2), 那么暴力求每个点后续有几个数大于自己, 然后求删去前面所有数和后续大于自己数的代价, 最后遍历最小值即可.

code

void func(void)
{
	int n,mx = 0;
	cin >> n;
	vector<int> a(n),cnt(n);
	for(auto &i : a)	cin >> i;
	for(int i=0;i<n;++i)
	{
		for(int j=i+1;j<n;++j)
		{
			if(a[j] > a[i])	cnt[i] ++;
		}
	}
	int ans = M;
	for(int i=0;i<n;++i)
	{
		ans = min(ans,i+cnt[i]);
	}
	cout << ans << '\n';
}

C

思路

设数组实际长度为 len, 对于每个数字, 在 len+1i 时可以被使用, 而1i 固定
, 那么就可以处理出每个数字在什么长度时可以被使用, 且同效果(长度)数只能被使用一次

那么每个数只会从能变为此效果的数转移而来,
dp[b[i]+i1]=dp[b[i]]+i1, b[i]+i1 代表新的可获得长度, b[i]为转移前长度.

卡题原因

dp不熟练

code

void func(void)
{
	int n,ans = 0;
	cin >> n;
	int len = n;
	vector<int> a(n+1),b(n+1),c;
	map<int,bool> cvis;
	map<int,int> dp;
	map<int,vector<int>> mp;
	for(int i=1;i<=n;++i)	cin >> a[i];
	for(int i=1;i<=n;++i)
	{
		b[i] = a[i] - (len-i+1);
		if(b[i] == 0)
		{
			c.push_back(i);
		}
		if(b[i] >= 0)	mp[b[i]].push_back(i);
	}
	dp[0] = n;
	cvis[0] = true;
	for(auto &temp : mp)
	{
		if(cvis.count(temp.x) == 0)	continue;
		for(auto &i : temp.y)
		{
			cvis[b[i]+i-1] = true;
			dp[b[i]+i-1] = max(dp[b[i]+i-1],dp[temp.x]+i-1);
		}
	}
	for(auto &i : dp)	ans = max(ans,i.y);
	cout << ans << '\n';
}

D

思路

完全背包.

未ac原因

先是没看到 1nm3105,
后是把 b 单调减遗忘了.

补题还二分总写不出来, 实际甚至可以不二分.

code

void func(void)
{
	int n,m,ans = 0,mx = 0;
	cin >> n >> m;
	vector<int> a(n+1),s(n+1),b(m+1);
	vector<vector<int>> dp(m+1,vector<int>(n+1,M));
	for(int i=1;i<=n;++i)
	{
		cin >> a[i];
		mx = max(a[i],mx);
		s[i] = s[i-1] + a[i];
	}
	for(int i=1;i<=m;++i)
	{
		cin >> b[i];
	}
	if(mx > b[1])
	{
		cout << -1 << '\n';
		return ;
	}
	dp[0][0] = 0;
	for(int i=1;i<=m;++i)
	{
		for(int j=0;j<=n;++j)
		{
			dp[i][j] = dp[i-1][j];
			if(j == 0)	continue;
			int k=0;
			int be = 0,ed = j;
			while(be != ed-1)
			{
				int mid = (be+ed) >> 1;
				if(s[j]-b[i] <= s[mid])	ed = mid;
				else	be = mid;
			}
			dp[i][j] = min(dp[i][j],dp[i][(s[j]-b[i] <= s[be] ? be : ed)]+m-i);
		} 
	}
	cout << dp[m][n] << '\n';
}
posted @   zerocloud01  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示