Educational Codeforces Round 24

本文解析了四道算法题目,包括使用二分查找解决问题的方法、序列构造问题、矩阵中的对象定位以及前缀和问题,提供了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A

好傻的,我还用了二分

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int qq = 2e5 + 10;
LL n, k;
bool Check(LL x){
	if(x == 0)	return true;
	if((n / 2 - x) / x >= k)	return true;
	return false;
}

int main(){
	cin >> n >> k;
	LL l = 0, r = n / 2, mid;
	LL ans = 0;
	while(l <= r){
		mid = (l + r) / 2;
		if(Check(mid)){
			ans = mid;
			l = mid + 1;
		}else{
			r = mid - 1;
		}
	}
	printf("%lld %lld %lld\n", ans, ans * k, n - (ans + ans * k));
	return 0;
}

B

题意:n个数(1~n)组成的序列,m次操作,每次操作数i,然后到数字为i + ai的地方,如此操作下去,求符合要求的数组a

思路:直接枚举第一个数再数组a中的位置,然后check即可

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int qq = 2e5 + 10;
int n, m;
int num[105];
int loca[105];
int vis[105];
map<int, bool> mp;
int x[105];
bool Check(){
	mst(vis, 0);
	for(int i = 1; i <= n; ++i){
		if(!num[i])	continue;
		if(!vis[num[i]])	vis[num[i]] = 1;
		else	return false;
	}
	return true;
}

int main(){
	cin >> n >> m;
	REP(i, 1, m){
		scanf("%d", loca + i);
	}
	bool f = false;
	for(int i = 1; i <= n; ++i){
		mst(num, 0);
		num[i] = loca[1];
		bool t = true;
		for(int j = 2; j <= m; ++j){
			int a = loca[j - 1], b = loca[j];
			int cnt = 0;
			while(1){
				++a, ++cnt;
				if(a > n)	a = 1;
				if(a == b)	break;
			}
			if(!num[loca[j - 1]]){
				num[loca[j - 1]] = cnt;
			}else{
				if(num[loca[j - 1]] != cnt){
					t = false;
					break;
				}
			}
		}
/*		for(int j = 1; j <= n; ++j)
			printf("%d ", num[j]);
		puts("");*/
		if(!t)	continue;
		if(!Check())	continue;
		if(t){
			f = true;
			break;
		}	
	}
	if(!f){
		puts("-1");
		return 0;
	}
	for(int i = 1; i <= n; ++i){
		mp[num[i]] = true;
	}
	int cnt = 0;
	for(int i = 1; i <= n; ++i){
		if(!mp[i])	x[cnt++] = i;
	}
	cnt = 0;
	for(int i = 1; i <= n; ++i){
		if(!num[i])	num[i] = x[cnt++];
	}
	for(int i = 1; i <= n; ++i)
		printf("%d ", num[i]);
	puts("");
	return 0;
}

C

题意:由d个沙发,分布在n × m的矩阵内,然后给出numl, numr, numt, numb分别代表某个沙发左边,右边,上边,下边的沙发数量,让你求出这个沙发的index,一个沙发占两个有公共边的格子。

思路:分四个方向分别统计前缀和后缀,然后枚举每一个沙发,看是否满足所给定的沙发数量

#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define pill pair<int, int>
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int qq = 2e5 + 10;
int dirc[qq][4];
int point[qq][4];

int main(){
	int d, n, m;
	scanf("%d%d%d", &d, &n, &m);
	REP(i, 1, d){
		scanf("%d%d%d%d", &point[i][0], &point[i][2], &point[i][1], &point[i][3]);
		if(point[i][0] > point[i][1])	swap(point[i][0], point[i][1]);
		if(point[i][2] > point[i][3])	swap(point[i][2], point[i][3]);
		REP(j, 0, 3){
			dirc[point[i][j]][j]++;
		}
	}
	int cntl, cntr, cntt, cntb;
	scanf("%d%d%d%d", &cntl, &cntr, &cntt, &cntb);
	for(int i = 1; i <= n; ++i)
		dirc[i][0] += dirc[i - 1][0];
	for(int i = n; i >= 1; --i)
		dirc[i][1] += dirc[i + 1][1];
	for(int i = 1; i <= m; ++i)
		dirc[i][2] += dirc[i - 1][2];
	for(int i = m; i >= 1; --i)
		dirc[i][3] += dirc[i + 1][3];
	for(int i = 1; i <= d; ++i){
		int l = point[i][0], r = point[i][1], b = point[i][2], t = point[i][3];
		int numl = dirc[r - 1][0], numr = dirc[l + 1][1], numt = dirc[t - 1][2], numb = dirc[b + 1][3];
		if(l == r){
			numt--, numb--;
		}else{
			numl--, numr--;
		}
		if(numl == cntl && numr == cntr && numt == cntt && numb == cntb){
			printf("%d\n", i);
			return 0;
		}
	}
	puts("-1");
	return 0;
}

D

题意:给定n个数,然后一个数字B,问是否存在一个数A,对于数字A的前缀和在任意一个i都满足cntA(i) >= cntB(i),求出这个数。

思路:恩~~~感觉想到了就是很简单的,看代码吧。

我感觉实际上可以这样想,就是对于每一个数字B与数字B之间都要存在某个数,注意第一个B前面也要存在。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <utility>

using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#define mst(a, b)	memset(a, b, sizeof a)
#define REP(i, x, n)	for(int i = x; i <= n; ++i)
const int qq = 1e6 + 10;
int num[qq];
int n, A;
map<int, int> mp;

int main(){
	scanf("%d%d", &n, &A);
	for(int i = 1; i <= n; ++i){
		int x;	scanf("%d", &x);
		if(x == A)	num[A]++;
		else if(num[x] >= num[A])	num[x]++;
	}
	for(int i = 1; i <= 1e6; ++i)
		if(i != A && num[i] >= num[A]){
			printf("%d\n", i);
			return 0;
		}
	puts("-1");	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值