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 ;
}