Codeforces Round 996 (Div. 2) C、D题

C题

一 题目

二 思路

我们设每行总和为x,每列的总和为y,那么会有x=y。一共有n行m列,那么矩阵的总和可以表示为nx或者my,那么nx=my。如果n和m不相同,而x=y,那么x和y只能是0。所以,当n不等于m时候,行或者列的总和只能是0。当n和m相同时则可以为任何数,这里为了方便,我们统一行或者列的总和都是0。

因为每次只能向下或者向右,不能向上或者向左,所以每次可以确定一个点的值是多少,随后依次确定每个点的值就可以知道答案。可以证明,当路线向右时,说明行方向至少还有两个未知数,这时候列方向就只有一个未知数,反之,路线向下时,行方向只有一个未知数。在知道总和为0的情况下,就可以依次求出每个值是多少了。

三 代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1010;
int arr[N][N];//读入数据 
int prerow[N],precol[N];//第i行总和,第i列总和 
string s;//读入数据 
void solve()
{
	int n,m;cin>>n>>m;
	for(int i=1;i<=n;i++)prerow[i]=0;//初始化 
	for(int j=1;j<=m;j++)precol[j]=0;//初始化 
	cin>>s;
	for(int i=1;i<=n;i++)//求每行总和 
	{
		for(int j=1;j<=m;j++)
		{
			cin>>arr[i][j];	
			prerow[i]+=arr[i][j];
		}	
	} 
	for(int j=1;j<=m;j++)//求每列总和 
	{
		for(int i=1;i<=n;i++)
		{
			precol[j]+=arr[i][j];
		}	
	} 
	int i=1,j=1;
	for(int k=0;k<n+m-2;k++)//每次确定一个点,让总和=0 
	{
		if(s[k]=='R')
		{
			arr[i][j]=-precol[j];
			precol[j]=0;
			prerow[i]+=arr[i][j];
			j++;
		}
		else
		{
			arr[i][j]=-prerow[i];
			prerow[i]=0;
			precol[j]+=arr[i][j];
			i++;
		}
	}
	arr[i][j]=-prerow[i],prerow[i]=0,precol[j]=0;
	for(int i=1;i<=n;i++)//输出结果 
	{
		for(int j=1;j<=m;j++)
		{
			cout<<arr[i][j]<<' ';
		}
		cout<<'\n';
	}
}
signed main()
{
	ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);
	int t;cin>>t;
	while(t--)solve();
	return 0;
}

D题

一 题目

二 思路

 这道题要求需要的时间,其实就是稻草人移动的距离。那么我们不如把所有东西都扩大2倍,除了稻草人的移动距离还是1,而不是2。这样求出来的时间就是2倍时间了。

这道题分为两种情况:乌鸦在稻草人的左边和右边

1.乌鸦在第i个稻草人的右边

那就是第i个稻草人向左移动,同时第i-1个稻草人向右移动,迫使乌鸦与第i个稻草人重合后跳跃,此时会花费的时间就是两者之间的距离/2

2.乌鸦在第i个稻草人的左边

那么答案会是第i个稻草人移动到离乌鸦最近的位置,然后让乌鸦跳跃。乌鸦在稻草人左边是一定能让稻草人跳跃的,因为i-1个稻草人让乌鸦跳跃了k的位置,那么第i个稻草人在乌鸦左边,说说明距离一定小于k的位置。

3.如果最后没有稻草人让乌鸦跳跃了,那么就是最后一个稻草人慢慢推着乌鸦到目的地,加上距离即可。

三 代码

#include<iostream>
#define int long long
using namespace std;
const int N=200010;
int arr[N];
void solve()
{
	int n,k,l;
	cin>>n>>k>>l;
	k*=2,l*=2;//将所有都扩大两倍,除了移动的单位距离,这样就把时间扩大两倍了
	for(int i=1;i<=n;i++)
	{
		cin>>arr[i];
		arr[i]*=2;	
	} 
	int ans=arr[1],x=k;//表示花费的时间*2,现在乌鸦到达哪个位置 
	for(int i=2;i<=n;i++)
	{
		if(arr[i]>x)//乌鸦在第i个稻草人右边 
		{
			arr[i]=max(x,arr[i]-ans);
			ans+=(arr[i]-x)/2;
			x=(x+arr[i])/2+k;
		}
		else//乌鸦在第i个稻草人左边 
		{
			arr[i]=min(x,arr[i]+ans);
			x=arr[i]+k;
		}
	}
	if(x<l)
	{
		ans+=l-x;
	}
	cout<<ans<<'\n';
}
signed main()
{
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值