Codeforces #541 题解(A.B.C.D.F)

Codeforces #541 题解(A.B.C.D.F)

前言:差点上青.jpg,F比D还简单

ABC是考场写的。

其实DF的算法自己都会,还是要提高自己的知识水平

A

题意:给定两个矩形,它们是左对齐的,第一个矩形在下,且第一个矩形的宽大于第二个(\(w_1>w_2\))。求与它们相邻格子的个数。

题解:显然,\(ans=w_1+w_2+(h_1+h_2)\times 2 + (w_1-w_2)\)

B

题意:一场比赛,记录了\(n\)次得分,最后一次为结束时的得分。求比赛过程中,有多少次双方平局。

题解:简单模拟,但细节较多。

#include<bits/stdc++.h>
using namespace std;
int n,lasta,lastb,a,b,ans;
int main()
{
    cin>>n;
    lasta=lastb=0;
    cin>>a>>b;
    ans+=min(a,b) - max(lasta,lastb)+1; 
    lasta=a;lastb=b;
    for (int i=2;i<=n;i++)
    {
        cin>>a>>b;
        if (a==lasta&&b==lastb) continue; 
        ans+=max(min(a,b) - max(lasta,lastb)+1,0);
        if (lasta==lastb) ans--; 
        lasta=a;lastb=b;
    } 
    cout<<ans<<endl;
    return 0;
}

C

题意:给出一个序列,要排成一个圈,求排列使得相邻两个数的相差最小。

题解:大概就是第二个小的数在第一小的左边,第三小的数在第一小右边,第四小的在第二小左边,以此类推。我不会证明

#include<bits/stdc++.h>
using namespace std;
int n,a[150],ans[150];
int main()
{
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    sort(a+1,a+n+1);
    for (int i=1;i<=n/2;i++)
    {
        ans[i]=  a[i*2 -1];
        ans[n-i+1]= a[i*2];
    }
    if (n%2)
    {
        ans[n/2 +1] =a[n];
    }
    for (int i=1;i<=n;i++)
    {
        cout<<ans[i]<<" ";
    }
    return 0;
} 
D

题意:有长度为\(n\)\(m\)的两个序列,给出大小关系,求方案使最大值最小,且最大值用得尽量小。

题解:差分约束会\(TLE\),而拓扑保证不了\(=\)的情况。其实本题正解为拓扑+并查集。将\(=\)的数合起来,再建大于小于的边,进行拓扑。若拓扑失败,则输出\(no\)

#include<bits/stdc++.h>
using namespace std;
int cc,to[1000010],net[1000010],fr[3000],ind[3000],fa[3000];
int q[3000],ans[3000],n,m;char ch[1010][1010];
void addedge(int u,int v)
{
    cc++;
    to[cc]=v;net[cc]=fr[u];fr[u]=cc;ind[v]++;
}
int fafa(int x)
{
    if (fa[x]==x) return x;
    return fa[x]=fafa(fa[x]);
}
void hebing(int x,int y)
{
    x=fafa(x);y=fafa(y);
    fa[x]=y;
}
bool topsort()
{
    int h=1,t=0;
    for (int i=1;i<=n+m;i++)
      if (!ind[i]) q[++t]=i,ans[i]=1;
    while (h<=t)
    {
        for (int i=fr[q[h]];i;i=net[i])
        {
            ind[to[i]]--;
            if (ind[to[i]]==0) 
            {
                q[++t]=to[i];
                ans[to[i]]=ans[q[h]]+1;
            }
        }
        h++;
    }
    for (int i=1;i<=n+m;i++)
      if (ind[fafa(i)]) return false;
    return true;
}

int main()
{
    cin>>n>>m;
    for (int i=1;i<=n+m;i++) 
    {
        fa[i]=i;
    }
    for (int i=1;i<=n;i++)
    {
        cin>>ch[i];
        for (int j=1;j<=m;j++)
        {
            if (ch[i][j-1]=='=') hebing(i,j+n);
        }
    }
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
        {
            if (ch[i][j-1]=='<') 
              addedge(fafa(i),fafa(j+n));
            if (ch[i][j-1]=='>')
              addedge(fafa(j+n),fafa(i));
        }
    if (topsort())
    {
        cout<<"Yes\n";
        for (int i=1;i<=n;i++)
        {
            cout<<ans[fafa(i)]<<" ";
        } 
        cout<<endl;
        for (int i=1+n;i<=m+n;i++)
        {
            cout<<ans[fafa(i)]<<" ";
        }
    }
    else 
    cout<<"No\n";
    return 0;
} 

F

题意:有一个长度为\(n\)的序列,每次将两个数所在的序列(必须相邻)合并起来,求合法的序列

题解:考察链表的应用,CF难度评分\(1700\)?

写的有点丑,将就看吧。

#include<bits/stdc++.h>
using namespace std;
int fa[150100],fa1[150100],n,x,y;
struct data
{
    int head,tail;
}a[150100];
int fafa(int x)
{
    if (fa[x]==x) return x;
    return fa[x]=fafa(fa[x]);
}
int fafa1(int x)
{
    if (fa1[x]==x) return x;
    return fa1[x]=fafa1(fa1[x]);
}
void hebing(int x,int y)
{
    x=fafa(x);y=fafa(y);
    fa[x]=y;
}
void hebing1(int x,int y)
{
    x=fafa1(x);y=fafa1(y);
    fa1[y]=x;
}
int main()
{
    cin>>n;
    for (int i=1;i<=n;i++) fa[i]=i,fa1[i]=i;
    for (int i=1;i<n;i++)
    {
        cin>>x>>y;
        x=fafa(x);y=fafa1(y);
        a[x].tail=y;
        a[y].head=x;
        hebing(x,y);
        hebing1(x,y);
    }
    for (int i=fafa(1);i;i=a[i].head)
    {
        cout<<i<<" ";
    }
    return 0;
}

转载于:https://www.cnblogs.com/fmj123/p/10430409.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值