Codeforces Round 944 (Div. 4)A~G详解

A

#include <iostream>

using namespace std;

int main () {
	int n;
	cin>>n;
	while(n--) {
		int a,b;
		cin>>a>>b;
		if(a < b) {
			int c = a;
			a = b;
			b = c;
		}
		cout<<a<<b;
	}

	return 0;
}

B

#include <bits/stdc++.h>

using namespace std;

int main () {
	int n;
	cin>>n;
	while(n--) {
		string str;
		cin>>str;
		bool flag = true;
		int n = str.length();
		for(int i = 0;i < n;i++) {
			for(int j = 0;j < n;j++) {
				if(str[i] != str[j]){
					flag = false;
					swap(str[i],str[j]);
					break;
				}
			}
			if(!flag) break;
		} 
		if(flag) {
			cout<<"NO"<<endl;
		}else{
			cout<<"YES"<<endl;
			cout<<str<<endl;
		}
	}

	return 0;
}

C

首先通过a和b的值来将钟表的时间分为不包含他们俩的两个区间,然后分别判断c和d是否满足一人一个区间,不能一个区间脚踏两只船吧

#include <bits/stdc++.h>

using namespace std;

int main () {
	int n;
	cin>>n;
	while(n--) {
		vector<int> num1;
		vector<int> num2;
		int a,b,c,d;
		cin>>a>>b>>c>>d;
		bool flag = false;
		if(a > b) swap(a,b);
		for(int i = a + 1; i < b; i++) num1.push_back(i);
		for(int i = 1; i < a; i++) num2.push_back(i);
		for(int i = b + 1; i <= 12; i++) num2.push_back(i);

		int n1 = num1.size();
		int n2 = num2.size();
		for(int i = 0; i < n1; i++) {
			if(c == num1[i]) {
				flag = true;
				break;
			}
		}
		if(flag) {
			flag = false;
			for(int i = 0; i < n2; i++) {
				if(d == num2[i]) {
					flag = true;
					break;
				}
			}
		} else {
			for(int i = 0; i < n1; i++) {
				if(d == num1[i]) {
					flag = true;
					break;
				}
			}
			if(flag) {
				flag = false;
				for(int i = 0; i < n2; i++) {
					if(c == num2[i])  {
						flag = true;
						break;
					}
				}
			}
		}
		if(flag) {
			cout<<"YES"<<endl;
		} else {
			cout<<"NO"<<endl;
		}
	}
	return 0;
}

D

首先看一段二进制字符串可以怎么分,如果有连续几个1,就要分一块,那么再看这一块的前后是否含0,如果前面有0就将前面的0一块加上,后面的0不用管,当然这时候就有0又有1 的这一块只能分一个,不然就构不成最小的那个数了。我们的目的就是将所有的1从后向前排然后再排0。
另一种简单的思路:将结果初始化为1,因为如果原字符串不需要变动,这也是一块;然后就是计算01 或 10 这种情况有多少种;最后就是判断是否有这种情况存在,如果存在就将结果 -1 。

#include <iostream>

using namespace std;

int main () 
{
	int t;
	cin>>t;
	while(t--) 
	{
		string str;
		cin>>str;
		int res = 0;
		bool flag = false;
		for(int i = str.length()-1;i >= 0;)
		{
			if(str[i] == '0') 
			{
				res ++;
				while(str[i] == '0') i--;
			}else if(str[i] == '1') 
			{
				while(str[i] == '1') i--;
				if(!flag && i >= 0 && str[i] == '0') {
					flag = true;
					while(str[i] == '0') i--;
				}
				res ++;
			}
		}
		cout<<res<<endl; 
	}
	return 0;
}

E

通过二分在a数组中找出第一个大于查找节点的位置,然后就算多出来的这部分时间加上之前的即可

#include <iostream>
#include <cstring>

using namespace std;

const int N = 100010;
int a[N],b[N];

int main () 
{
	int t;
	scanf("%d",&t);
	while(t--) 
	{
		int n,k,q;
		scanf("%d%d%d",&n,&k,&q);
		
		for(int i = 1;i <= k;i ++){
			scanf("%d",&a[i]);
		}
		for(int i = 1;i <= k;i ++){
			scanf("%d",&b[i]);
		}
		while(q--) {
			int x;
			scanf("%d",&x);
			int l = 0,r = k;
			if(x == 0) {
				cout<<"0 ";
				continue;
			}
			while(l < r) {
				int mid = (l+r) >> 1;
				if(a[mid] <= x) l = mid + 1;
				else r = mid;
				
			}
			int d = x - a[l-1];
			long long sth = (long long)d*(b[l] - b[l-1])/(a[l] - a[l-1]);
			cout<<sth + b[l-1]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

F

首先只需要计算第一象限中的点数,然后 x 4 + 4 即可。通过遍历纵坐标,然后二分横坐标,遵循大范围-小范围的思想,存在这样的式子:$r2<=x2+y2<(r+1)2$ 那么二分的时候找到第一个小于$r^2$位置,那么用大范围-小范围即可

#include <iostream>
#include <cstring>

using namespace std;

typedef long long LL;


const int N = 100010;
int a[N],b[N];
double c[N];

int main () {
	int t;
	scanf("%d",&t);
	while(t--) {
		int d;
		scanf("%d",&d);
		int res = 0;
		for(int i = 1; i <= d; i++) {
			int tl = 0;
			int l = 0,r = d;
			while(l < r) {
				int mid = l + r + 1 >> 1;
				if((LL)mid * mid + (LL)i * i < (LL)d * d) l = mid;
				else r = mid - 1; 
			}
			tl = l;
			l = 0,r = d;
			while(l < r) {
				int mid = l + r + 1 >> 1;
				if((LL)mid * mid + (LL)i * i < (LL)(d + 1) * (d + 1)) l = mid;
				else r = mid - 1;
			}
			res += r - tl;
		}
		cout<<4+4*res<<endl;
	}
	return 0;
}

G

使用了一个Map集合,并且要知道一个规律,满足$a_i>>2 == a_j>>2$这个条件的两个值是可以交换的,Map集合的定义:k为$a_i>>2$,v为所有$a_i>>2$相等的值的序列,然后将Map中的每一个序列进行排序,这就会满足字典序最小。最后将Map集合中的所有序列存入到a数组中,并且从后往前存储。

#include <bits/stdc++.h>

using namespace std;

const int N = 100010;
int a[N],b[N];
double c[N];

int main () {
	int t;
	scanf("%d",&t);
	while(t--) {
		int n;
		scanf("%d",&n);
		map<int,vector<int>> m;
		vector<int> q(n+1);
		for(int i = 1; i <= n; i++) {
			scanf("%d",&q[i]);
			m[q[i] >> 2].push_back(q[i]);
		}
		for(auto &t :m) {
			sort(t.second.begin(),t.second.end());
		}
		for(int i = n; i; i--) {
			q[i] = m[q[i] >> 2].back();
			m[q[i] >> 2].pop_back();
		}
		for(int i = 1; i <= n; i++) {
			printf("%d ",q[i]);
		}
		puts("");
	}
	return 0;
}
posted @ 2024-05-19 17:26  zhy_Debug  阅读(73)  评论(0)    收藏  举报