CF赛后总结1:2021-07-10晚 #731 div3 rating+393

  • 题库链接:link<-----div3#731题库

  • A题:link 模拟题

  • 1、题意:给出三个点,在1000X1000的平面内输出不过点三,点一到点二的最小距离

  • 2、转化:搜索 [X] 复杂度太大,于是想到找规律,在起始点之间或者之外的点,对二者的曼哈顿距离不影响,在其上的点曼哈顿距离加二

  • 3、代码:

#include<iostream>
#include<cmath>
using namespace std;
int main()
{
    int x1, y1, x2, y2, x3, y3;
    int t; cin >> t;
    while (t--)
    {
        int ans = 0;
        cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
        if ((x3 == x1 && x3 == x2 && y3 < y2 && y3 > y1) || (x3 == x1 && x3 == x2 && y3 > y2 && y3 < y1))
        {
            ans = fabs(x1 - x2) + fabs(y1 - y2) + 2;
        }
        else if ((y3 == y1 && y3 == y2 && x3 <  && x3 > ) || (y3 == y1 && y3 == y2 && x3 > x2 && x3 < x1))
        {
            ans = fabs(x1 - x2) + fabs(y1 - y2) + 2;
        }
        else ans = fabs(x1 - x2) + fabs(y1 - y2);
        cout << ans << endl;
    }
    return 0;
}

  • B题: link 模拟题
  • 1、题意:对于空的s每次对其加上字母表上的字母,从a开始要是符合字母表就输出YES否则输出NO,课题加在前面也可以加在后面就从a当起始位置开始找
  • 2、思路:找到a找不到直接输出NO然后模拟双指针添加元素直到完成长度等于s.size()就正确,否则错误
  • 3、代码:
#include<iostream>
using namespace std;
int main()
{
    int t; cin >> t;
    while (t--)
    {
        string s;
        cin >> s;
        int pos = -1;
        for (int i = 0; i < s.size(); i++)
            if (s[i] == 'a')
                pos = i;
        int l = pos, r = pos;
        int k = 0;
        int cnt = 0;
        while (l >= 0 && r < s.size() && cnt < s.size())
        {
            if (l > 0 && s[l - 1] == (char)(k + 1 + 'a'))
            {
                k++, l--;
            }
            if (r < s.size() && s[r + 1] == (char)(k + 1 + 'a'))
            {
                k++, r++;
            }
            cnt++;
        }
        if (pos != -1 && k == s.size() - 1)puts("YES");
        else puts("NO");
    }
}
  • C题: link 模拟题
  • 1、题意:如果修改的行小于len则是可行修改,可以有两种操作,一种是上面的可行修改,然后是加新行,都不可行则不可行
  • 2、转化:如果修改和加新行都可行,率先加新行,如果不能加新行,判断修改是否可行,可行加上修改,不可行则不可行
  • 代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N = 110, M = N * 2;
int a[N], b[N], ans[M];
int main()
{
	int t; cin >> t;
	while (t--)
	{
		memset(a, 0, sizeof a);
		memset(b, 0, sizeof b);
		memset(ans, 0, sizeof ans);
		int len; cin >> len;
		int aa, bb;
		cin >> aa >> bb;
		for (int i = 0; i < aa; i++)cin >> a[i];
		for (int j = 0; j < bb; j++)cin >> b[j];
		a[aa] = 1e9, b[bb] = 1e9;
		int k = 0;
		int i = 0, j = 0;
		bool flag = true;
		while (1)
		{
			if (a[i] == 0 && b[j] != 0)
			{
				if (b[j] <= len)ans[k++] = b[j], j++;
				else
				{
					ans[k++] = 0;
					i++, len++;
				}
			}
			else if (a[i] != 0 && b[j] == 0)
			{
				if (a[i] <= len)ans[k++] = a[i], i++;
				else
				{
					ans[k++] = 0;
					j++, len++;
				}
			}
			else if (a[i] == 0 && b[j] == 0) ans[k++] = 0, i++, len++;
			else
			{
				if (a[i] <= len)ans[k++] = a[i], i++;
				else if (b[j] <= len)ans[k++] = b[j], j++;
				else
				{
					if (k == aa + bb)break;
					else
					{
						flag = false;
						break;
					}
				}
			}

		}
		if (flag)
		{
			for (int i = 0; i < k; i++)cout << ans[i] << ' ';
			cout << endl;
		}
		else puts("-1");
	}
	return 0;
}
  • D题:link
  • 题意:给出一个数组,求与其元素对应的异或数组(ans数组)满足异或后的答案数组呈题目描述的增长状态,即 ai 含有的二进制的1,ai+1 一定也含有就是题目描述的增长
  • 转化:对应的异或数组的第一位一定是0,n==1直接输出0,然后就是知道前一项的异或和,知道后一项的 ai-1 算出前一项的 ansi 按数位判断数位分为四种情况,x代表前一项的异或结果,y代表后一项的异或结果,按数位来
  • x=1,y=1不用管,不加异或x有的y都有
  • x=0,y=0同理
  • x=0,y=1不用管,y有的x没有,可以操作,但是操作后不满足异或后的值大于异或前的值,与题意不符,所以不操作
  • x=1,y=0要管为了异或为1,所以加上当前位为1的二进制权值
  • 代码:
#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int a[N];

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n; cin >> n;
		for (int i = 0; i < n; i++) cin >> a[i];
		if (n == 1) cout << 0 << endl;
		else
		{
			vector<int>ans(n);
			ans[0] = 0;
			for (int i = 1; i < n; i++)
			{
				ll x = a[i - 1] ^ ans[i - 1];
				ll y = a[i];
				ll sum = 0, val = 1;
				while (x)
				{
					ll a1 = (x & 1), b1 = (y & 1);
					if (a1 == 1 && b1 == 0)sum += val;
				    x >>= 1, y >>= 1, val <<= 1;
				}
				ans[i] = sum;
			}
			for (int i = 0; i < n; i++) cout << ans[i] << ' ';
			cout << endl;
		}
	}
	return 0;
}
  • E题:link
  • 题意:先输入房间数量,再输入空调个数,然后空调所在格的温度就是空调温度,前后格温度加加,输出每个格的最小温度
  • 转化:就是模拟,前面来一遍,后面来一遍求前后遍历两个值的min
  • 代码:
#include<iostream>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
const int N = 3e5 + 10;
ll pos[N], temp[N];
ll ans[N];
int main()
{
	int t; cin >> t;
	while (t--)
	{
		int n, m;
		cin >> n >> m;
		for (int i = 1; i <= m; i++)cin >> pos[i];
		for (int i = 1; i <= m; i++)cin >> temp[i];
		for (int i = 1; i <= n; i++)ans[i] = 2e9;
		for (int i = 1; i <= m; i++)ans[pos[i]] = temp[i];
		for (int i = 1; i < n; i++)
		{
			ans[i + 1] = min(ans[i] + 1, ans[i + 1]);
		}
		for (int i = n; i > 1; i--)
		{
			ans[i - 1] = min(ans[i] + 1, ans[i - 1]);
		}
 
		for (int i = 1; i <= n; i++)cout << ans[i] << ' ';
		cout << endl;
	}
	return 0;
}
  • 2021-07-14写于南宁

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值