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) 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;
}
原文地址:https://www.cnblogs.com/fmj123/p/10430409.html