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) imes 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
";
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
";
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;
}