Educational Codeforces Round 62 (Rated for Div. 2)(题解)

Educational Codeforces Round 62 (Rated for Div. 2)(题解)

A. Detective Book

题目大意

现在有一本侦探书,其每页上有一些秘密,会在后面的页码中出现,每天会一直看书直到所有的秘密都已经被了解了,问需要几天将书看完

解题思路

从前向后遍历,如果当前所读的页中,揭秘来得最晚的也已经被揭秘了则算一天.

AC代码

#include<bits/stdc++.h>
using namespace std;
int arr[10005];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>arr[i];
	int ans=0;
	int maxn=0;
	for(int i=1;i<=n;i++)
	{
		maxn=max(maxn,arr[i]);
		if(maxn<=i) ans++;
		else continue;
	}
	cout<<ans<<endl;
} 	

B. Good String

题目大意

给出一段由大于号小于号组成的字符串,每次右括号可以消去其右边的一个字符,左括号可以消去其左边的一个字符.问一个字符串需要预先去掉多少的字符使得其最终可以削成一个字符.

解题思路

当字符串左端点为>或者右端点为<时可以最终削成一个字符.选择需要去掉较少字符的那一段消去字符使其为前面说的两个字符作为端点

AC代码

#include<bits/stdc++.h>
using namespace std;
int main()
{ 
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		string s;
		cin>>s;
		int ans=n;
		int temp=0;
		for(int i=0;i<n;i++)
		{
			if(s[i]=='<')  temp++;
			else break;
		}
		ans=min(ans,temp);
		temp=0;
		for(int i=n-1;i>=0;i--)
		{
			if(s[i]=='>') temp++;
			else break;
		}
		ans=min(ans,temp);
		cout<<ans<<endl;
	}
}

C. Playlist

题目大意

给出n首歌,每首歌都有一定的趣味值和长度,一个歌曲集合的趣味度之和为歌曲的总长度乘上趣味值得最小值,现在要选出最多k首歌构成一个趣味值尽可能大的集合

解题思路

对所有的歌曲根据歌曲的趣味程度从小到大排序.从后向前,则当前的歌曲的趣味度总是最小的.每次得出一个答案即当前歌曲向后所有的歌的长度的前k大的和与答案比较得出最大值即可.每次完成后将当前歌曲的长度放入set中,总长度sum加上这首歌曲的总长度,当set满k-1个后就弹出长度最小的那个并且使得总长度减去长度最小的那个

AC代码

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int sz=3e5+5;
typedef pair<int,int> pii;
pii s[sz];
int len[sz];
multiset<int> se;
int32_t main()
{
	int n,k;
	cin>>n>>k;
	se.clear();
	for(int i=1;i<=n;i++)
	{
		scanf("%lld%lld",&s[i].second,&s[i].first);
		len[i]=s[i].second;
	}
	sort(s+1,s+1+n);
	int ans=0;
	int sum=0;
	for(int i=n;i>=1;i--)
	{
		ans=max(ans,s[i].first*(s[i].second+sum));
		se.insert(s[i].second);
		sum+=s[i].second;
		if(se.size()==k)
		{
			sum-=*(se.begin());
			se.erase(se.begin());
		}
	}
	cout<<ans<<endl;
}

D. Minimum Triangulation

题目大意

给出一个正n边形.每个顶点从1-n,将正n边形分割成三角形使得有最小的三角形顶点积之和

解题思路

理性分析一波就知道,所有的三角形都要有顶点1更好点

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
	int n;
	scanf("%d",&n);
	long long  sum=0;
	for(int i=2;i<n;i++)
	{
		sum=sum+1LL*i*(i+1);
	}
	cout<<sum<<endl;
}

E. Palindrome-less Arrays

题目大意

我们定义一段序列为bad序列当其有子串满足长度为大于1 的奇数且其前后对称时.现在给出一段序列,其中一些位置留空,给出一个上限k问有多少种填法使得有对序列留空部分填入1-k之间的数字使得其不为bad序列

解题思路

最短的前后对称的子序列就是长度为3只要保证没有这种长度的对称子序列就可以是good序列,第一个数字和第三个数字相同的子序列.由此将原序列分成奇偶串,即问有多少种填法,使奇偶串不存在相邻项相同的情况.由此,对奇偶串中每段连续的-1作容斥即可.需要注意的是,当前后相等时不需要再容斥上-1串长度为0的情况.

AC代码

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int mod=998244353;
int quick_pow(int a,int b){int ans=1;while(b){if(b&1) ans=ans*a%mod;a=a*a%mod;b>>=1;} return ans;}
int n,k;
int ex_solve(int len,bool f)
{
	int ans=0;
	bool s=0;
	for(int i=len;i>=f;i--)
	{
		s^=1;
		if(s&1)ans=(ans+quick_pow(k-1,i))%mod;
		else ans=(ans-quick_pow(k-1,i)+mod)%mod;
	}
	return ans;
}
int solve(vector<int> v)
{
	int len=v.size();
	int front=0,end=len-1;
	int t=1;
	int maxn=-1;
	for(auto x:v) maxn=max(maxn,x);
	if(maxn<0) return quick_pow(k-1,len-1)*k%mod;
	while(v[front]==-1) front++,t=t*(k-1)%mod;
	int ans=1;
	ans=ans*t%mod;
	t=1;
	while(v[end]==-1) end--,t=t*(k-1)%mod;
	ans=ans*t%mod;
	t=1;
	int pre=front;
	for(int i=front+1;i<=end;i++)
	{
		if(v[i]>0)
		{
			int l=i-pre-1;
			ans=ans*ex_solve(l,v[i]==v[pre])%mod;
			pre=i;
		}
	}
	return ans;
}
int32_t main()
{
	cin>>n>>k;
	int x;
	vector<int> odd,even;
	for(int i=1;i<=n;i++)
	{
		cin>>x;
		if(i%2) odd.push_back(x);
		else even.push_back(x);
	}
	cout<<solve(odd)*solve(even)%mod<<endl;
}

猜你喜欢

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