Codeforces Round #541 (Div. 2)(题解)

Codeforces Round #541 (Div. 2)(题解)

A. Sea Battle

题目大意

给出两个长方形,其左边界对其,一个摆放在另一个上,问其周长

解题思路

较长的宽乘二,长相加乘二再加上四个角即为周长

AC代码

#include<bits/stdc++.h>
using namespace std;
#define int long long 
int32_t main()
{
	int w1,d1,w2,d2;
	cin>>w1>>d1>>w2>>d2;
	cout<<w1*2 +2*d1+2*d2+4<<endl;
}

B. Draw!

题目大意

给出一场比赛中几个时刻的比分,问从始至终,共存在多少平分的时刻

解题思路

在两个相邻的时段之间可以产生的的比分相同的次数为上一时段所能达到的最大值减去这一时段的较小值,为了防止重复,其还需要大于上一次的较大的比分

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define int long long
int a[10005],b[10005];
int32_t main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i]>>b[i];
	}
	int ans =0;
	a[0]=b[0]=0;
	int last=0;
	for(int i=0;i<n;i++)
	{
		ans+=max(0LL,min(a[i+1],b[i+1])-max({a[i],b[i],last})+1);
		last=min(b[i+1],a[i+1])+1;
	}
	cout<<ans<<endl;
}

C. Birthday

题目大意

给出一些数字,要求构建一个数字环,使得相邻两个数的差值最小

解题思路

对数排序之后,从前向后放置奇数位,从后向前放置偶数位

AC代码

#include<bits/stdc++.h>
using namespace std;
int arr[105];
int ans[105];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>arr[i];
	sort(arr+1,arr+1+n);
	for(int i=1;i<=n;i++)
	{
		if(i&1)
		ans[i/2+1]=arr[i];
		else ans[n-i/2+1]=arr[i];
	}
	for(int i=1;i<=n;i++) cout<<ans[i]<<' ';
}

D. Gourmet choice

题目大意

给出两组菜,与两组菜之间两两的美味程度的大小比较,现要求对菜从小到大进行评分,要求所有给出的评分都尽可能低.如一开始给出的美味程度有矛盾则输出No

解题思路

假如一道菜比另一道菜更加美味,则从更加不美味的菜向另一道菜连接一条边权为1的边,如美味程度相等则连接边权为0的双向边.枚举每个未被访问的点进行dfs,点权即为父点的点权加上边权.如出现环,则冲突

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
int dep[2005];
bool vis[2005];
char s[1005];
vector<pii> G[2005];
bool dfs(int u,int deps)
{
	vis[u]=1;
	for(auto x:G[u])
	{
		int v=x.first;
		int ndep=deps+x.second;
		if(dep[v]<ndep)
		{
			if(vis[v]) return false;
			dep[v]=ndep;
			if(!dfs(v,ndep)) return false;
		}
	}
	vis[u]=0;
	return true;
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		for(int j=1;j<=m;j++)
		{
			if(s[j]=='=') G[i].push_back(pii(j+n,0)),G[j+n].push_back(pii(i,0));
			if(s[j]=='>') G[j+n].push_back(pii(i,1));
			if(s[j]=='<') G[i].push_back(pii(j+n,1));
		}
	}
	memset(vis,0,sizeof(vis));
	bool flag=1;
	for(int i=1;i<=n+m;i++)
	{
		flag=dfs(i,0);
		if(!flag) break;
	}
	int bottom=0;
	if(!flag) cout<<"No"<<endl;
	else
	{
		cout<<"Yes"<<endl;
		for(int i=1;i<=n+m;i++) bottom=min(bottom,dep[i]);
		for(int i=1;i<=n;i++) cout<<dep[i]-bottom+1<<' ';cout<<endl;
		for(int i=n+1;i<=n+m;i++) cout<<dep[i]-bottom+1<<' ';cout<<endl;
	}
}

E. String Multiplication

题目大意

给出一种字符串之间的乘法操作,如给出一个长度为m的字符串s和一个字符串t则 s t = t + s 1 + t + s 2 + t + . . . + s m + t s\cdot t=t+s_1+t+s_2+t+...+s_m+t 现给出n个字符串令为 p 1 , p 2 , p 3 . . . p n p_1,p_2,p_3...p_n ( . . . ( ( ( p 1 p 2 ) p 3 ) . . . ) p n ) (...(((p_1\cdot p_2)\cdot p_3)\cdot ...)*p_n) 中最长的连续字母有多长

解题思路

可以发现每次乘法操作后,某个字母最长的连续字串的长度只与新乘上的字符串中该字母的最长连续长度或者通过与其他的新乘串有关.令新串为t,之前已经得到的字符串称为s,s中第j个字母最长连续的长度为lens[j]则当t中全为字母j时,新串中的连续长度就可能为 l e n s [ j ] ( t + 1 ) + t lens[j]*(|t|+1)+|t| 如s中存在字母j且,t前面有连续pre个字母j,t后面有连续suf个字母j则新串可能的最大长度就为 p r e + s u f + 1 pre+suf+1 ,无论如何其总有t中连续的字母j的最长长度,比较几个可能的答案得出则得出了这一轮相乘之后的答案,最后都乘晚后, a n s = m a x i = 0 , 1 , 2...25 ( l e n [ i ] ) ans=max_{i=0,1,2...25}(len[i])

AC代码

#include<bits/stdc++.h>
using namespace std;
string s;
int con[27],mcon[27];
int lens[27];
int main()
{
	int n;
	scanf("%d",&n);
	int pre,suf;
	int ans=0;
	memset(lens,0,sizeof(lens));
	while(n--)
	{
		cin>>s;
		int len=s.length();
		memset(con,0,sizeof(con));
		memset(mcon,0,sizeof(mcon));
		for(int i=0;i<len;i++)
		{
			if(i&&s[i]==s[i-1]) con[s[i]-'a']++;
			else con[s[i]-'a']=1;
			mcon[s[i]-'a']=max(mcon[s[i]-'a'],con[s[i]-'a']);
		}
		for(int i=0;i<26;i++)
		{
			pre=0,suf=len-1;
			while(pre<len&&s[pre]=='a'+i) pre++;
			while(suf>=0&&s[suf]=='a'+i) suf--;
			if(pre==len) lens[i]=max(mcon[i],lens[i]*(len+1)+len);
			else if(lens[i]) lens[i]=max(mcon[i],pre+len-suf);
			else lens[i]=mcon[i];
			if(!n)ans=max(ans,lens[i]);
		}		
	}
	cout<<ans<<endl;
}

F. Asya And Kittens

题目大意

给出n只猫,其标号从1-n,每天给出两个标号其表示,这两个猫住在相邻的位置,且接下来将合并他们的住处,现将给出n-1次合并,问猫一开始的居住位置

解题思路

对每只猫的都维护一个首并查集,和尾并查集即可

AC代码

#include<bits/stdc++.h>
using namespace std;
const int size=150005;
int fa[size];
int son[size];
int nx[size];
bool vis[size];
int findf(int x)
{
	return x==fa[x]?x:fa[x]=findf(fa[x]);
}
int finds(int x)
{
	return x==son[x]?x:son[x]=finds(son[x]);
}
void merge(int s,int f)
{
	int sf=findf(s),ff=findf(f);
	int ss=finds(s),fs=finds(f);
	fa[sf]=ff;
	son[fs]=ss;
}
int main()
{
	int n;
	cin>>n;
	int x,y;
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++) fa[i]=i,son[i]=i;
	for(int i=1;i<n;i++)
	{
		cin>>x>>y;
		nx[findf(y)]=finds(x); vis[finds(x)]=1;
		merge(y,x);
	}
	int beg=-1;
	for(int i=1;i<=n;i++) if(!vis[i]) {beg=i;break;}
	vector<int> ans;
	while(fa[beg]!=beg) ans.push_back(beg),beg=nx[beg];
	ans.push_back(beg);
	for(auto u:ans) cout<<u<<' ';
}
	
	

猜你喜欢

转载自blog.csdn.net/baiyifeifei/article/details/88235303