GDUT 寒假排位赛三

题目链接:】http://codeforces.com/group/NVaJtLaLjS/contest/238202

感想 emmmm,这套题有个特点,代码量小的考思维,而那些一眼看过去思路就有了,就是模拟到你死,代码量超级大,毫无疑问一遇到模拟题我就枯,所以这次被lwk锤爆

A. Out of Sorts(思维)
题意: 给你一个数组,问你需要经过几次冒泡排序,使其变成一个有序的数组
GDUT 寒假排位赛三_第1张图片
思路: 由于在冒泡排序过程中,会把一个较大的数往后面排,在这过程中有一些数也会被动交换,所以我们只需要找到一个需要移到前面最大的次数(也就是说有多少个数向后面移动,每次冒泡只会把一个最大的数移到最后,有几个数就需要冒多少次)

#include
#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
#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(模拟)
题意: 给你一些人之间的关系树,问里面两个人之间有什么关系
GDUT 寒假排位赛三_第2张图片思路: 找到两个人最近的公共祖先,计算节点的深度从而判断除二者之间的关系,若没有公共祖先则没有关系,若判断A是B的侄女,应该反过来写成 B是A的姑姑

#include
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(思维+树状数组)
题意: 对冒泡排序进行改良,变成双向冒泡,问需要冒几次,才能把一个序列变成有序
GDUT 寒假排位赛三_第3张图片
思路: 由于双向,所以每次都有一个小的往前冒,一个大的往后冒,所以我们需要求在前i个位置里面在排序之后,却不在前i个位置里面的个数,遍历1-n求出最大的个数,用树状数组优化一下,得出冒泡的次数

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

你可能感兴趣的:(GDUT集训)