Educational Codeforces Round 91 (Rated for Div. 2)赛后总结

A - Three Indices

You are given a permutation p1,p2,…,pn. Recall that sequence of n integers is called a permutation if it contains all integers from 1 to n exactly once.

Find three indices i, j and k such that:

1≤i<j<k≤n;
pipk.
Or say that there are no such indices.
Input
The first line contains a single integer T (1≤T≤200) — the number of test cases.

Next 2T lines contain test cases — two lines per test case. The first line of each test case contains the single integer n (3≤n≤1000) — the length of the permutation p.

The second line contains n integers p1,p2,…,pn (1≤pi≤n; pi≠pj if i≠j) — the permutation p.

Output
For each test case:

if there are such indices i, j and k, print YES (case insensitive) and the indices themselves;
if there are no such indices, print NO (case insensitive).
If there are multiple valid triples of indices, print any of them.

Example
inputCopy
3
4
2 1 4 3
6
4 6 1 2 5 3
5
5 3 1 2 4
outputCopy
YES
2 3 4
YES
3 5 6
NO

题意:
给出n个数,求找出三个下标依次上升的数a,b,c,使得b最大,输出下标。

思路:
暴力,l[i]标记起始位置到i的最小值所处的位置,r[i]标记终点位置到i的最小值所处的位置,判定,若l[i]!=i&&r[i]!=i,那么该值符合题意。

代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<cstdio>
using namespace std;
typedef long long ll;
int inf = 0x3f3f3f3f;
const ll N = 2e5+5;
int a[1005];
int main()
{
	int t;
    int n, i;
    bool flag;
	cin >> t;
	while (t--)
	{
       scanf("%d",&n);
		for(i=1;i<=n;i++)scanf("%d",&a[i]);
		mn=maxn;
		for(i=1;i<=n;i++)
			if(mn>a[i])mn=a[i],l[i]=i;
			else l[i]=l[i-1];
		mn=maxn;
		for(i=n;i>=1;i--)
			if(mn>a[i])mn=a[i],r[i]=i;
			else r[i]=r[i+1];
		flag=0;
		for(i=1;i<=n;i++)
			if(l[i]!=i&&r[i]!=i)
			{
				flag=1;break;
			}
		if(flag)printf("YES\n"),printf("%d %d %d\n",l[i],i,r[i]);
		else printf("NO\n");
	}
	return 0;
}

B - Universal Solution

Recently, you found a bot to play “Rock paper scissors” with. Unfortunately, the bot uses quite a simple algorithm to play: he has a string s=s1s2…sn of length n where each letter is either R, S or P.

While initializing, the bot is choosing a starting index pos (1≤pos≤n), and then it can play any number of rounds. In the first round, he chooses “Rock”, “Scissors” or “Paper” based on the value of spos:

if spos is equal to R the bot chooses “Rock”;
if spos is equal to S the bot chooses “Scissors”;
if spos is equal to P the bot chooses “Paper”;
In the second round, the bot’s choice is based on the value of spos+1. In the third round — on spos+2 and so on. After sn the bot returns to s1 and continues his game.

You plan to play n rounds and you’ve already figured out the string s but still don’t know what is the starting index pos. But since the bot’s tactic is so boring, you’ve decided to find n choices to each round to maximize the average number of wins.

In other words, let’s suggest your choices are c1c2…cn and if the bot starts from index pos then you’ll win in win(pos) rounds. Find c1c2…cn such that win(1)+win(2)+⋯+win(n)n is maximum possible.

Input
The first line contains a single integer t (1≤t≤1000) — the number of test cases.

Next t lines contain test cases — one per line. The first and only line of each test case contains string s=s1s2…sn (1≤n≤2⋅105; si∈{R,S,P}) — the string of the bot.

It’s guaranteed that the total length of all strings in one test doesn’t exceed 2⋅105.

Output
For each test case, print n choices c1c2…cn to maximize the average number of wins. Print them in the same manner as the string s.

If there are multiple optimal answers, print any of them.

Example
Input
3
RRRR
RSP
S
Output
PPPP
RSP
R
Note
In the first test case, the bot (wherever it starts) will always choose “Rock”, so we can always choose “Paper”. So, in any case, we will win all n=4 rounds, so the average is also equal to 4.

In the second test case:

if bot will start from pos=1, then (s1,c1) is draw, (s2,c2) is draw and (s3,c3) is draw, so win(1)=0;
if bot will start from pos=2, then (s2,c1) is win, (s3,c2) is win and (s1,c3) is win, so win(2)=3;
if bot will start from pos=3, then (s3,c1) is lose, (s1,c2) is lose and (s2,c3) is lose, so win(3)=0;
The average is equal to 0+3+03=1 and it can be proven that it’s the maximum possible average.
A picture from Wikipedia explaining “Rock paper scissors” game:
题意
石头(R)剪刀(S)布(P),给出一段机器的序列,要求你输出自己的一段序列来跟机器比赛使得总成绩最大,且总成绩是与机器序列n个不同起点开始的不同序列的比赛成绩平均值。
思路:
用贪心去做,直接先遍历一遍找到数量最多的那个就行。
代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<cstdio>
using namespace std;
typedef long long ll;
int inf = 0x3f3f3f3f;
const ll N = 2e5+5;
int a[1005];
int main()
{
	int t;
    int n, i;
    bool flag;
	cin >> t;
	while (t--)
	{
		string str; cin>>str;
        char ans;
        int r=0,s=0,p=0;
        for(int i=0;i<str.length();i++){
            if(str[i]=='R') r++;
            else if(str[i]=='S') s++;
            else p++;
        }
        if(p>=r&&p>=s) ans = 'S';
        else if(r>=p&&r>=s) ans = 'P';
        else ans = 'R';
        for(int i=0;i<str.length();i++) cout<<ans;
        cout<<endl;
        }
	return 0;
}

C - Create The Teams

There are n programmers that you want to split into several non-empty teams. The skill of the i-th programmer is ai. You want to assemble the maximum number of teams from them. There is a restriction for each team: the number of programmers in the team multiplied by the minimum skill among all programmers in the team must be at least x.

Each programmer should belong to at most one team. Some programmers may be left without a team.

Calculate the maximum number of teams that you can assemble.

Input
The first line contains the integer t (1≤t≤1000) — the number of test cases.

The first line of each test case contains two integers n and x (1≤n≤105;1≤x≤109) — the number of programmers and the restriction of team skill respectively.

The second line of each test case contains n integers a1,a2,…,an (1≤ai≤109), where ai is the skill of the i-th programmer.

The sum of n over all inputs does not exceed 105.

Output
For each test case print one integer — the maximum number of teams that you can assemble.

Example
Input
3
5 10
7 11 2 9 5
4 8
2 4 2 3
4 11
1 3 3 7
Output
2
1
0
题意:
给出n个元素,要求分成尽可能多的组,使得每组内最小值*组的大小 ≥ x。

思路:
贪心,对这些程序员的技能进行排序,从最高的开始分,这样就可以满足团队的数量最大。

代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<cstdio>
using namespace std;
typedef long long ll;
int inf = 0x3f3f3f3f;
const ll N = 2e5+5;
int a[1005];
int main()
{
	int t;
    int n, x;
    bool flag;
	cin >> t;
	while (t--)
	{
		scanf("%d%d", &n, &x);
		for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
		sort(a + 1, a + n + 1);
		int ans = 0, len = 1;
		for (int i = n; i >= 1; i--) {
			if (a[i] * len >= x) {
				len = 1;
				ans++;
			}
			else len++;
		}
		printf("%d\n", ans);
	}
	return 0;
}

D - Berserk And Fireball

There are n warriors in a row. The power of the i-th warrior is ai. All powers are pairwise distinct.

You have two types of spells which you may cast:

Fireball: you spend x mana and destroy exactly k consecutive warriors;
Berserk: you spend y mana, choose two consecutive warriors and the warrior with greater power destroys another chosen warrior.
For example, let the powers of warriors be [2,3,7,8,11,5,4], and k=3. If you cast Berserk on warriors with powers 8 and 11, the resulting sequence of powers becomes [2,3,7,11,5,4]. Then, for example, if you cast Fireball on consecutive warriors with powers [7,11,5], the resulting sequence of powers becomes [2,3,4].

You want to turn the current sequence of warriors powers a1,a2,…,an into b1,b2,…,bm. Calculate the minimum amount of mana you need to spend on it.

Input
The first line contains two integers n and m (1≤n,m≤2⋅105) — the length of sequence a and the length of sequence b respectively.

The second line contains three integers x,k,y (1≤x,y,≤109;1≤k≤n) — the cost of fireball, the range of fireball and the cost of berserk respectively.

The third line contains n integers a1,a2,…,an (1≤ai≤n). It is guaranteed that all integers ai are pairwise distinct.

The fourth line contains m integers b1,b2,…,bm (1≤bi≤n). It is guaranteed that all integers bi are pairwise distinct.

Output
Print the minimum amount of mana for turning the sequnce a1,a2,…,an into b1,b2,…,bm, or −1 if it is impossible.

Examples
Input
5 2
5 2 3
3 1 4 5 2
3 5
Output
8
Input
4 4
5 1 4
4 3 1 2
2 4 3 1
Output
-1
Input
4 4
2 1 11
1 3 2 4
1 3 2 4
Output
0
题意:
n个战士排成一排,分别有个武力值a[i]。你有两种法术,一个是火球(花费x个法力,消灭连续k个战士),一个是激怒(花费y个法力,选择相邻两个战士,武力值大的会消灭武力值小的)。求最后留下的战士排列成b[i]需要的最小法力花费

思路:
贪心:
首先只有三种情况:
1.都用方案1,有剩余则对剩余的使用方案二。
2.都用方案2.
3.在2的基础上可能会出现区间内最大值大于两个端点。所以我们可以用方案一消除那些最大值,最终也能消除掉区间内的所有数字。当然这个前提是这个区间长度大于等于k。
求最大值直接O(n)去求就行,时限2s,处理各个区间也是O(n),因为中间那个while循环的缘故是不会超时的

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inf=0x3f3f3f3f3f3f3f3f;
const int N=2e5+10;
int n,m,x,y,k;
ll a[N],b[N],p[N];
void solve()
{
    int f,flag=0;
    ll ans=0,res;
    for(int i=1;i<m;i++)
    {
        res=inf;
        f=0;
        ll ma=0,len=0;
        for(int j=p[i]+1;j<=p[i+1]-1;j++) ma=max(ma,a[j]),len++;
        if(ma>max(a[p[i]],a[p[i+1]])&&len>=k) res=min(res,(len-k)*y+x),f=1;
        if(ma<max(a[p[i]],a[p[i+1]])) res=min(res,len*y),f=1;
        if(len>=k) res=min(res,len/k*x+len%k*y),f=1;
        if(!f)
        {
            flag=1;
            break;
        }
        ans+=res;

    }
    ll ma=0,len=0;
    f=0,res=inf;
    for(int j=1;j<=p[1]-1;j++) ma=max(ma,a[j]),len++;
    if(ma>a[p[1]]&&len>=k) res=min(res,(len-k)*y+x),f=1;
    if(ma<a[p[1]]) res=min(res,len*y),f=1;
    if(len>=k) res=min(res,len/k*x+len%k*y),f=1;
    if(!f)
    {
        cout<<-1<<endl;
        return;
    }
    ans+=res;
    f=0,res=inf;
    ma=0,len=0;
    for(int j=p[m]+1;j<=n;j++) ma=max(ma,a[j]),len++;
    if(ma>a[p[m]]&&len>=k) res=min(res,(len-k)*y+x),f=1;
    if(ma<a[p[m]]) res=min(res,len*y),f=1;
    if(len>=k) res=min(res,len/k*x+len%k*y),f=1;
    if(!f)
    {
        cout<<-1<<endl;
        return;
    }
    ans+=res;
    if(flag) cout<<-1<<endl;
    else cout<<ans<<endl;
}
int main()
{
    cin>>n>>m;
    cin>>x>>k>>y;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=m;i++) cin>>b[i];
    int pos=1,flag=0;
    for(int i=1;i<=m;i++)
    {
        while(a[pos]!=b[i]&&pos<=n) pos++;
        if(pos==n+1)
        {
            flag=1;
            break;
        }
        p[i]=pos;
        pos++;
    }
    if(flag) cout<<-1<<endl;
    else solve();
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值