Educational Codeforces Round 64 (Rated for Div. 2)

A题

题意:1 表示圆,2表示等腰三角形(底等于高),3 表示正方形。给出一个数组表示不同的形状,问嵌套之后相交的点有几个,若有边重合则说明有无数点重合,输出Infinite ,否则输出Finite和重合的点有几个。
题解:
判断当前和后面的形状然后加点数就行,但是有一个特殊情况就是正方形里面有一个圆形,圆形里有一个三角形,此时有一个重复的点,这种情况减一即可。

#include <cstdio>
const int N = 105 ; 
int a[N] ; 
int main(){
	int n ; 
	scanf ("%d",&n) ;
	for (int i = 1 ; i <= n ; ++ i){
		scanf ("%d",&a[i]) ;
	}
	int cnt = 0 ;
	for (int i = 1 ; i < n ; ++ i){
		if (a[i] == 1)	{
			if (a[i+1] == 2)	cnt += 3 ; 
			else if (a[i+1] == 3)	cnt += 4 ; 
		}
		else if (a[i] == 2)	{
			if (a[i+1] == 3){
				printf ("Infinite\n") ; 
				return 0 ; 
			}
			else if (a[i+1] == 1)	cnt += 3 ; 
		}	 
		else if (a[i] == 3){
			if (a[i+1] == 2){
				printf ("Infinite\n") ; 
				return 0 ; 
			}
			else if (a[i+1] == 1){
				cnt += 4 ; 
				if (a[i+2] == 2 && i <= n-2)	-- cnt ; 
			}	
		}
	}
	printf ("Finite\n%d\n",cnt) ;
	return 0 ; 
} 
B题

题意:给出一串字符串,要求交换字符位置使得该字符串中没有存在在字母表中相邻的字符。
题解:先将字符串排序,然后用两个队列存放,一个字符标记a队列的队尾元素,遍历字符串,若和a队尾元素无冲突的就压入a队列,若冲突就压入b队列,最后判断a队尾和b队头 或者 a队头和b队尾 是否冲突,然后拼接就可以了,若两种情况都冲突就输出No answer

#include <iostream>
#include <string>
#include <algorithm>
#include <queue>
using namespace std ; 
int main(){
	int t ; 
	cin >> t ; 
	while(t --){
		string s ; 
		cin >> s ; 
		sort(s.begin(),s.end()) ;
		queue<char> a , b ; 
		a.push(s[0]) ; 
		char tail = s[0] ;
		int n = s.length() ; 
		for (int i = 1 ; i < n ; ++ i){
			if (s[i]-tail == 1)		b.push(s[i]) ;	//当a的队尾和当前字符冲突就将当前字符压入b队中 
			else{
				a.push(s[i]) ;	//无冲突继续压入a中 
				tail = s[i] ; 
			}	
		}
		s = "" ; //将s置空 
		int flag = 0 ; 
		if (abs(tail-b.front()) != 1){
			while(!a.empty())	s += a.front() , a.pop() ;
			if (abs(s[s.length()-1] - b.front()) ==  1)		flag = 1 ; 
			while(!b.empty())	s += b.front() , b.pop() ;
		}
		else{
			while(!b.empty())	s += b.front() , b.pop() ;
			if (abs(s[s.length()-1] - a.front()) == 1)		flag = 1 ; 
			while(!a.empty())	s += a.front() , a.pop() ;
		}
		if (flag)	cout << "No answer" << endl ; 
		else	cout << s << endl ; 
	}
	return 0 ; 
}
C题

题意:给出一个长度为n的数组和m,问该数组中有多少个|a[i] - a[j]| >= m
题解:先排序然后用两个指针移动,i的范围是0 ~ n/2 , j的范围是n/2 ~ n然后就是遍历啦。

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std ;
const int N = 2e5 + 5 ; 
int a[N] ; 
int main(){
	int n , m ; 
	scanf ("%d%d",&n,&m) ;
	for (int i = 0; i < n ; ++ i)	scanf ("%d",&a[i]) ;
	int i = 0 , j = n/2 , cnt = 0 ;
	sort(a,a+n) ;
	while(i < n/2 && j < n){
		if (a[j] - a[i] >= m){
			++ cnt ; 
			++ i ; 
			++ j ; 
		}
		else	++ j ; 
	}
	printf ("%d\n",cnt) ;
	return 0 ; 
}
D - 0-1-Tree

题意:给出图,点之间相连的边为1 或 0 ,问有多少对(x,y)x != y 满足x到y先0后1 。
题解:在这里插入图片描述
题解来源→ 大佬题解

#include <cstdio>
const int N = 2e5 + 5 ;
int fa[N] , fb[N] ;
int da[N] , db[N] ;
int find1(int x){
	if (x != fa[x])
		fa[x] = find1(fa[x]) ;
	return fa[x] ; 
} 
int find2(int x){
	if (x != fb[x])
		fb[x] = find2(fb[x]) ; 
	return fb[x] ;
}
int main(){
	int n ; 
	scanf ("%d",&n) ;
	for (int i = 1 ; i <= n ; ++ i)	{
		fa[i] = i , fb[i] = i ; 
		da[i] = 1 , db[i] = 1 ; 
	}	
	int x , y , w ; 
	for(int i = 1 ; i < n ; ++ i){
		scanf("%d%d%d",&x,&y,&w) ; 
		if (w == 1){	//包含 1 的树 
			x = find1(fa[x]) , y = find1(fa[y]) ;
			if (x != y)		fa[x] = y ; 
			da[y] += da[x] ;
		}	
		else{		// 包含 0 的树 
			x = find2(fb[x]) , y = find2(fb[y]) ;
			if (x != y)		fb[x] = y ;
			db[y] += db[x] ;  
		}
	}
	long long ans = 0 ; 
	for (int i = 1 ; i <= n ; ++ i){
		ans += (long long)da[find1(i)] * db[find2(i)] - 1 ; 
	}
	printf ("%lld\n",ans) ;
	return 0 ; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值