Codeforces Round #799 (Div. 4) A-E

目录

A

B

C

D

E

A

Problem - A - Codeforces
You are given four distinct integers a, b, c, d.

Timur and three other people are running a marathon. The value a is the distance that Timur has run and b, c, d correspond to the distances the other three participants ran.

Output the number of participants in front of Timur.
题意:

给出abcd四个值问a是第几大。

思路:

记录有几个大于a的数

#include<bits/stdc++.h>
#pragma warning (disable:4996);
#define ll long long
#define	int ll
#define mm(a) memset(a,0,sizeof(a))
using namespace std;
const int N = 2e5 + 10;
int T, n, m, k, q;
int a, b, c, d;

signed main() {
	ios::sync_with_stdio(0); cout.tie(0);
#ifndef ONLINE_JUDGE
	freopen("out.txt", "w", stdout);
#endif	
	cin >> T;
	while (T--) {
		int ans = 0;
		int mx = -1;
		 {
			cin >> a;
			for (int j = 1; j <= 3; j++) {
				cin >> b;
				if (b > a)
					ans++;
			}
		}
		cout << ans << endl;
	}
}

B

Problem - B - Codeforces

Sho has an array a consisting of n integers. An operation consists of choosing two distinct indices i and j and removing ai and aj from the array.

For example, for the array [2,3,4,2,5], Sho can choose to remove indices 1 and 3. After this operation, the array becomes [3,2,5]. Note that after any operation, the length of the array is reduced by two.

After he made some operations, Sho has an array that has only distinct elements. In addition, he made operations such that the resulting array is the longest possible.

More formally, the array after Sho has made his operations respects these criteria:

No pairs such that (i<j) and ai=aj exist.
The length of a is maximized.
Output the length of the final array.

题意:

给你一个数组,你每次可以选两个数删除,问你把数组变的没有重复元素后,数组最大长度是多少。

思路:

记录每个数的出现次数,首先如果一个数出现了奇数次,那么它可以不断操作减二直到只剩下一个元素。如果一个数出现了偶数次,但是出现偶数次的数的个数也为偶数的话,就可以每两个数各自减一,变成奇数然后就是情况1.所以最后的最大长度为odd+even

如果出现偶数次的数的个数为奇数的话,则必定会剩下一个出现次数为偶数的数不能和其他数配合从而不能去重。最大长度为odd+even-1.

#include<bits/stdc++.h>
#pragma warning (disable:4996);
#define ll long long
#define	int ll
#define mm(a) memset(a,0,sizeof(a))
using namespace std;
const int N = 2e5 + 10;
int T, n, m, k, q;
int a, b, c, d;

signed main() {
	ios::sync_with_stdio(0); cout.tie(0);
#ifndef ONLINE_JUDGE
	freopen("out.txt", "w", stdout);
#endif	
	cin >> T;
	while (T--) {
		cin >> n;
		vector<int>arr;
		int odd = 0, even = 0;
		int ans = 0;
		unordered_map<int, int>mp;
		for (int j = 0; j < n; j++) {
			cin >> a;
			mp[a]++;
		}
		for (auto x : mp) {
			if (x.second % 2 == 1) {
				odd++;
			}
			else {
				even++;
			}
		}
		if (even % 2 == 0)
			cout << odd + even << endl;
		else
			cout << odd + even - 1 << endl;
		
	}
}

 看了其他人的代码,发现有个更快的思路。假设最后只剩下去重的元素,长度为len,也就是说我们要删去n-len的元素,如果我们每次只能2个2个删,所以如果n-len是偶数则可以完全删完,只剩下完整的去重元素len。如果是奇数那么必定得多删一个才能保证没有重复元素。

for _ in range(int(input())):
    n=int(input())
    m=len(set(list(map(int,input().split()))))
    if (n-m)%2==1:
        print(m-1)
    else:
        print(m)

C

Problem - C - Codeforces

Mihai has an 8×8 chessboard whose rows are numbered from 1 to 8 from top to bottom and whose columns are numbered from 1 to 8 from left to right.

Mihai has placed exactly one bishop on the chessboard. The bishop is not placed on the edges of the board. (In other words, the row and column of the bishop are between 2 and 7, inclusive.)

The bishop attacks in all directions diagonally, and there is no limit to the distance which the bishop can attack. Note that the cell on which the bishop is placed is also considered attacked.

An example of a bishop on a chessboard. The squares it attacks are marked in red.

Mihai has marked all squares the bishop attacks, but forgot where the bishop was! Help Mihai find the position of the bishop
题意:

一个8*8的棋盘,有个棋子可以攻击它的对角线方向(攻击范围是‘#’),让你找到这个棋子的位置。而且这个棋子不会出现在边缘位置。

思路:

遍历然后判断这个点的特征

#include<bits/stdc++.h>
#pragma warning (disable:4996);
#define ll long long
#define	int ll
#define mm(a) memset(a,0,sizeof(a))
using namespace std;
const int N = 2e5 + 10;
int T, n, m, k, q;
int a, b, c, d;
mt19937 rd(time(0));

signed main() {
	ios::sync_with_stdio(0); cout.tie(0);
#ifndef ONLINE_JUDGE
	freopen("out.txt", "w", stdout);
#endif	
	cin >> T;
	while (T--) {
		string s[10];
		int x, y;
		int a1, a2;
		for (int j = 0; j < 8; j++) {
			cin >> s[j];
			int sum = 0;
		}
		for (int j = 1; j < 7; j++) {
			for (int i = 1; i < 7; i++) {
				if (s[j][i] == '#' && s[j - 1][i - 1] == '#'&&s[j-1][i]=='.'&&s[j+1][i]=='.' && s[j - 1][i + 1] == '#' && s[j][i - 1] == '.' && s[j][i + 1] == '.' && s[j + 1][i - 1] == '#' && s[j + 1][i + 1] == '#') {
					a1 = i;
					a2 = j;
					break;
				}
			}
		}
		cout << a2+1 << " " << a1+1 << endl;
	}
}

D

Problem - D - Codeforces

Victor has a 24-hour clock that shows the time in the format “HH:MM” (00 ≤ HH ≤ 23, 00 ≤ MM ≤ 59). He looks at the clock every x minutes, and the clock is currently showing time s.

How many different palindromes will Victor see in total after looking at the clock every x minutes, the first time being at time s?

For example, if the clock starts out as 03:12 and Victor looks at the clock every 360 minutes (i.e. every 6 hours), then he will see the times 03:12, 09:12, 15:12, 21:12, 03:12, and the times will continue to repeat. Here the time 21:12 is the only palindrome he will ever see, so the answer is 1.

A palindrome is a string that reads the same backward as forward. For example, the times 12:21, 05:50, 11:11 are palindromes but 13:13, 22:10, 02:22 are not.
题意:

给定起点时间,和间隔时间,问从起点时间开始可以遇到多少个回文时间。如 21:12

思路:

模拟时间变化即可,然后不断循环增加间隔时间,直到重复。

#include<bits/stdc++.h>
#pragma warning (disable:4996);
#define ll long long
#define	int ll
#define mm(a) memset(a,0,sizeof(a))
using namespace std;
const int N = 2e5 + 10;
int T, n, m, k, q;
int a, b, c, d;
mt19937 rd(time(0));
string add(string& s, int k) {
	string t = "";
	int j;
	for (j = 0; s[j] != ':'; j++)
		t += s[j];
	int hour = stoi(t);
	int mn = stoi(s.substr(j + 1, s.length() - j));
	int hour_n = k / 60;
	hour += hour_n;
	int mm = k % 60;
	if (mn + mm >= 60) {
		hour++;
		mn = (mn + mm) % 60;
	}
	else {
		mn = mn + mm;
	}
	hour %= 24;
	string h1 = "", m1 = "";
	if (hour < 10) h1 += "0";
	if (mn < 10) m1 += "0";
	return h1 + to_string(hour) + ":" + m1 + to_string(mn);
}
signed main() {
	ios::sync_with_stdio(0); cout.tie(0);
#ifndef ONLINE_JUDGE
	freopen("out.txt", "w", stdout);
#endif	
	cin >> T;
	while (T--) {
		string s;
		cin >> s >> n;
		unordered_map<string, int>mp;
		int ans = 0;
		while (mp[s] == 0) {
			int ok = 1;
			for (int j = 0, i = s.length() - 1; j != i;) {
				if (s[j] != s[i]) {
					ok = 0;
				}
				j++;
				i--;
			}
			mp[s] = 1;
			if (ok)ans++;
			s = add(s, n);
		}
		cout << ans << endl;
	}
}

E

Problem - E - Codeforces

Slavic has an array of length n consisting only of zeroes and ones. In one operation, he removes either the first or the last element of the array.

What is the minimum number of operations Slavic has to perform such that the total sum of the array is equal to s after performing all the operations? In case the sum s can’t be obtained after any amount of operations, you should output -1.


题意:

给定由01组成的数组,每次可以删除头部或者尾部元素。问使剩余数组的和为k的最小操作数。

思路:

题意很简单,就是找到等于k的前缀和,但是要最小操作,也就是如果有0就不能删了,这样才会满足结果且操作最少。所以去找前缀和为k的最长子段。因为前缀和数组是有序的,所以可以枚举一个右端点,二分查找使得子段和为k的左端点,然后还要使子段最长。二分左指针还要尽量左偏。

#include<bits/stdc++.h>
#pragma warning (disable:4996);
#define ll long long
#define	int ll
#define mm(a) memset(a,0,sizeof(a))
using namespace std;
const int N = 2e5 + 10;
int T, n, m, k, q;
int a, b, c, d;
int sum[N];
int myfind(int l, int r, int k, int s) {//s为右端点
	int mid = (l + r) >> 1;
	while (l + 1 != r) {
		mid = (l + r) >> 1;
		if (sum[mid] - sum[s - 1] <= k) {
			l = mid;//尽量左偏
		}
		else
			r = mid;
	}
	return l;
}
signed main() {
	ios::sync_with_stdio(0); cout.tie(0);
#ifndef ONLINE_JUDGE
	freopen("out.txt", "w", stdout);
#endif	
	cin >> T;
	while (T--) {
		cin >> n >> k;
		int ok = 1;
		int mx = INT_MIN;
		for (int j = 1; j <= n; j++) {
			cin >> a;
			sum[j] = sum[j - 1] + a;
		}
		for (int j = 1; j <= n; j++) {
			int ans = 0;
			int t = myfind(j - 1, n + 1, k, j);
			if (sum[t] - sum[j - 1] == k) {//二分的答案合法
				ok = 0;
				mx = max(mx, t - j + 1);
			}
		}
		if (ok)
            cout << -1 << endl;
		else 
			cout << n - mx << endl;
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值