这次的cf也就能写出A~C,B题挂了,所以补一下
本来只有B题,但还是把A和C的代码搬上来吧,简单解释
A:
https://codeforces.com/contest/1638/problem/A
题意:
给定长度为n的数组
可进行一次或0次操作:选定l和r(1 <= l,r <= n),逆序位置l到r的所有数组元素
输出进行操作后字典序最小的数组
分析:
最小的当然是1234567.....
当然不可能每次都能成这样,越高位决定权越大嘛,所以找到第一个与数位不对应的位置i作为l,数字i所在的位置作为r,逆序l到r的数组元素,然后输出就可以了,这道题我的代码很繁琐,不建议学习.......
比如用用continue;别if-else,先逆序再输出逻辑跟清晰等等
AC Code:
#include<bits/stdc++.h>
using namespace std;
int t,n;
int a[510];
void solve()
{
int l,r;
l = r = 0;
cin >>n;
for(int i = 1; i <= n; i++){
cin >>a[i];
if(a[i] != i && l == 0) l = i;
if(l != 0 && a[i] == l) r = i;
}
if(l == 0){
for(int i = 1; i <= n; i++){
cout <<a[i];
if(i != n) cout <<" ";
}
}
else{
if(l != 1)
for(int i = 1; i < l; i++){
cout <<a[i];
cout <<" ";
}
for(int i = r; i >= l; i--){
cout <<a[i];
cout <<" ";
}
if(r != n)
for(int i = r+1; i <= n; i++){
cout <<a[i];
cout <<" ";
}
}
cout <<endl;
}
int main(void)
{
cin >>t;
while(t--)
{
solve();
}
return 0;
}
B:https://codeforces.com/contest/1638/problem/B
题意:
给定长度为n的数组
可进行的操作:如果a[i]+a[i+1] (1 <= i <= n)是一个奇数,你可以swap(a[i],a[i+1])
现在问你能不能通过这个操作(不限次数)将原数组变为一个完全升序的数组
分析:
这题挂了
第一眼看到,这不就是加了个条件的冒泡排序么,然后就这样写了,预测试就过了,但没想到总共8组数据,昨天晚上只测四组。。。。。
接下来分析:
奇偶性相同的数相加一定是偶数
也就是说在数组的奇数元素子序列和偶数元素子序列里,元素的相对位置是不可改变的,至于偶数和奇数之间,哪怕大小位置不对,都是可调的。
所以思路也就是检验数组的奇数元素子序列和偶数元素子序列原本是不是有序的
AC Code:
#include<bits/stdc++.h>
using namespace std;
int t,n,x;
void solve()
{
bool ans = true;
cin >>n;
int ji,ou;
ji = ou = -1;
for(int i = 1; i <= n; i++){
cin >>x;
if(x & 1){
if(x < ji) ans = false;
else ji = x;
}
else{
if(x < ou) ans = false;
else ou = x;
}
}
if(ans) cout <<"YES" <<endl;
else cout <<"NO" <<endl;
}
int main(void)
{
std::ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >>t;
while(t--) solve();
return 0;
}
不得不说这题有去年ICPC南京站的C题感觉了
C: http://https://codeforces.com/contest/1638/problem/C
题意:
一个点数为n的无向图,无向图中的元素为1-n,有i,j,如果出现i < j && a[i] > a[j],则位置i和j之间出现一条边,问你这个无向图有多少个连通块
分析:
其实描述成数组更好理解,又有冒泡排序的意味了。
如果前x个元素是1~x的全排列,那这些元素就不会与后面的元素产生联系,就会出现一个连通块,就这样,注意好维护就行了,别又搞成n^2
AC Code:
#include <bits/stdc++.h>
using namespace std;
int t,n,x;
bool a[100010];
void solve()
{
memset(a,false,sizeof(a));
int res = 0,cnt = 0;
//cnt用来记录读入数据后是前多少的全排列
cin >>n;
for(int i = 1; i <= n; i++){
cin >>x; a[x] = true;
//如果是前i的全排列,连通块加一
if(x == cnt+1) cnt++;
while(a[cnt+1]) cnt++;
if(cnt == i)res++;
}
cout <<res <<endl;
}
int main(void)
{
std::ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >>t;
while(t--)
{
solve();
}
return 0;
}