【题目链接:】http://codeforces.com/group/NVaJtLaLjS/contest/238202
感想 emmmm,这套题有个特点,代码量小的考思维,而那些一眼看过去思路就有了,就是模拟到你死,代码量超级大,毫无疑问一遇到模拟题我就枯,所以这次被lwk锤爆
A. Out of Sorts(思维)
题意: 给你一个数组,问你需要经过几次冒泡排序,使其变成一个有序的数组
思路: 由于在冒泡排序过程中,会把一个较大的数往后面排,在这过程中有一些数也会被动交换,所以我们只需要找到一个需要移到前面最大的次数(也就是说有多少个数向后面移动,每次冒泡只会把一个最大的数移到最后,有几个数就需要冒多少次)
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
struct node
{
int x,id;
}a[100005];
bool cmp(node c,node d)
{
if(c.x==d.x)
return c.id<d.id;
return c.x<d.x;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].x);
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
int cnt=0,cnt1=0;
for(int i=1;i<=n;i++)
{
if(a[i].id>i)
cnt=max(a[i].id-i,cnt);
}
cout<<cnt+1<<endl;
return 0;
}
B. Milking Order(拓扑排序+二分)
题解链接: https://blog.csdn.net/qq_42819598/article/details/87925942
C. Team Tic Tac Toe(模拟)
题意: 井字棋,给出一个填好的图,问一个人赢的有几个,两个人组队赢的有几个
思路: 要注意这道题要去重例如一个人可能有好几组三个相连的,但是算一个赢,有个大佬的思路可以减少许多代码量的去重
一组去重比较容易,两组去重比较麻烦,可以把两个一组符合条件的就存两个不同的编号相加,这样就可以不用判重,每种情况都可以被存下来
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
char mp1[5][5];
int a[1000],mp[5][5],num[10],vis[1000];
int s(int i,int j,int k,int id)
{
if(i==j&&i==k){
a[id]=i;
return 1;
}
else if(i!=j&&j!=k&&i!=k){
a[id]=i+j+k;
return 3;
}
else if(i==j&&i!=k){
a[id]=i+k;
return 2;
}
else if(i==k&&i!=j){
a[id]=i+j;
return 2;
}
else if(k==j&&k!=i){
a[id]=k+j;
return 2;
}
return 0;
}
int main()
{
for(int i=0;i<3;i++)
cin>>mp1[i];
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
mp[i][j]=mp1[i][j]-'A'-'\0'+1;
}
int cnt=0,cnt1=0;
num[1]=s(mp[0][0],mp[0][1],mp[0][2],1);
num[2]=s(mp[1][0],mp[1][1],mp[1][2],2);
num[3]=s(mp[2][0],mp[2][1],mp[2][2],3);
num[5]=s(mp[0][0],mp[2][0],mp[1][0],5);
num[6]=s(mp[0][2],mp[1][2],mp[2][2],6);
num[7]=s(mp[0][1],mp[1][1],mp[2][1],7);
num[4]=s(mp[0][0],mp[1][1],mp[2][2],4);
num[8]=s(mp[0][2],mp[1][1],mp[2][0],8);
for(int i=1;i<=8;i++)
{
if(num[i]==1&&vis[a[i]]==0)
cnt++;
vis[a[i]]=1;
}
memset(vis,0,sizeof vis);
for(int i=1;i<=8;i++)
{
if(num[i]==2&&vis[a[i]]==0)
cnt1++;
vis[a[i]]=1;
}
cout<<cnt<<endl<<cnt1<<endl;
return 0;
}
D. Lemonade Line(签到提+贪心)
题意: 略
思路: 略
E. Family Tree(模拟)
题意: 给你一些人之间的关系树,问里面两个人之间有什么关系
思路: 找到两个人最近的公共祖先,计算节点的深度从而判断除二者之间的关系,若没有公共祖先则没有关系,若判断A是B的侄女,应该反过来写成 B是A的姑姑
#include<bits/stdc++.h>
using namespace std;
string mother[105],cow[105];
int n;
string fid(string a)
{
for(int i=1;i<=n;i++)
{
if(a==cow[i])
return mother[i];
}
return "";
}
int is(string a,string b)
{
int cnt=0;
while(b!="")
{
if(a==b)
return cnt;
b=fid(b);
cnt++;
}
return -1;
}
int main()
{
string a,b;
cin>>n>>a>>b;
for(int i=1;i<=n;i++)
{
cin>>mother[i]>>cow[i];
}
string now=a;
int cnta=0;
while(now!="")
{
if(is(now,b)!=-1)
break;
now=fid(now);
cnta++;
}
if(now=="")
{
cout<<"NOT RELATED"<<endl;
return 0;
}
int cntb=is(now,b);
if(cnta==cntb&&cnta==1)
{
cout<<"SIBLINGS"<<endl;
return 0;
}
else if(cnta>1&&cntb>1)
{
cout<<"COUSINS"<<endl;
return 0;
}
else {
if(cnta<cntb)
{
swap(a,b);
swap(cnta,cntb);
}
cout<<b<<" is the ";
for(int i=0;i<cnta-2;i++)
cout<<"great-";
if(cnta>1&&cntb==0)
cout<<"grand-";
if(cntb==0)
cout<<"mother";
else
cout<<"aunt";
cout<<" of "<<a<<endl;
}
return 0;
}
F. Out of Sorts II(思维+树状数组)
题意: 对冒泡排序进行改良,变成双向冒泡,问需要冒几次,才能把一个序列变成有序
思路: 由于双向,所以每次都有一个小的往前冒,一个大的往后冒,所以我们需要求在前i个位置里面在排序之后,却不在前i个位置里面的个数,遍历1-n求出最大的个数,用树状数组优化一下,得出冒泡的次数
#include<bits/stdc++.h>
using namespace std;
const int maxx=1e5+5;
struct node
{
int x,id;
}a[maxx];
bool cmp(node a,node b)
{
if(a.x==b.x)
return a.id<b.id;
return a.x<b.x;
}
int sum[maxx];
void add(int x)
{
while(x<maxx)
{
sum[x]++;
x+=x&(-x);
}
}
int ask(int x)
{
int ans=0;
for(int i=x;i>0;i-=i&(-i))
{
ans+=sum[i];
}
return ans;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i].x;
a[i].id=i;
}
int ans=0;
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
{
add(a[i].id);
ans=max(ans,i-ask(i));
}
cout<<max(ans,1)<<endl;
return 0;
}