Codeforces Round #723 (Div. 2)

Codeforces Round #723 (Div. 2)

A. Mean Inequality

在这里插入图片描述

Example

input

3
3
1 2 3 4 5 6
2
123 456 789 10
1
6 9

output

3 1 4 2 5 6
123 10 456 789
9 6

在这里插入图片描述

题目大意:

给一个2 n长的元素不重复的数组,任意交换位置,使得任一元素的左右两元素之和不等于本身的两倍,求这个新的数组。

思路:

先从简单的看起,假设a<b<c 或c<b<a, a+c=2 b,那么a,b,c就构成一个等差数列,我们的目的是让它不是等差数列,只要构造成b,a,c 或a,c,b就行了,即 高低高,低高低。

代码:

#include<algorithm>
#include<iostream>
#include<cmath>
#define int long long
using namespace std;

int a[100];

signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        n*=2;
        for(int i=0;i<n;++i)
        {
            cin>>a[i];
        }
        sort(a,a+n);
        for(int i=0;i<n/2;++i)
        {
            cout<<a[i]<<' ';
            cout<<a[n-i-1]<<' ';
        }
        cout<<endl;
    }
	return 0;
}


B. I Hate 1111

在这里插入图片描述

Example

input

3
33
144
69

output

YES
YES
NO

题目大意:

给你一个数,问你这个数能不能用任意个11,111,1111…相加得来。

思路:

数论,任意互质的正整数a,b,a* n+b* m所表示不出来的最大数是a* b-a-b.

因为11与111互质,所以11* 111-11-111=1099,即只要用这两个数字,就可以表示出>1099的数字,那么1-1099可以直接暴力求出来是否可以用11和111表示.

代码:

#include<algorithm>
#include<iostream>
#include<cmath>
#include<map>
#define int long long
using namespace std;

map<int,bool>ma;

signed main()
{
    int t;
    for(int i=0;i<=1100;i+=11)
    {
        for(int j=0;j<=1100;j+=111)
        {
            if(i+j<=1100)
            {
                ma[i+j]=1;//求1-1099可以被11和111表示出来的数字
            }
        }
    }
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        if(n>1099||ma[n])cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
	return 0;
}

简化版本:

signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        if(n/110>=n%11)cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
	return 0;
}

C. Potions

在这里插入图片描述

Example

input

6
4 -4 1 -3 1 -3

output

5

题目大意:

给一个数组,初始时你血量为0,元素从左到右,可以选择加上或者不加上,要求每时每刻血量不为负数,求最终最大的元素个数。

思路:

优先队列,从左到右,每个值都先吃进去,同时把负值塞入小顶堆优先队列,如果血量变成负数,就把之前吃进去的最小值吐出来,ans-1,每吃一个就求一次最大长度。

两题都可以这样做…好水啊。而且白书上面有原题…

代码:

#include<algorithm>
#include<iostream>
#include<cmath>
#define int long long
using namespace std;

priority_queue<int,vector<int>,greater<int>>p;

signed main()
{
    int n;
    cin>>n;
    int h=0;
    int ans=0;
    int temp=0;
    for(int i=0;i<n;++i)
    {
        int a;
        cin>>a;
        if(a<0)
        {
            p.push(a);
        }
        h+=a;
        ++temp;
        if(h<0)
        {
            --temp;
            h-=p.top();
            p.pop();
        }
        ans=max(ans,temp);
    }
    cout<<ans<<endl;
	return 0;
}

D. Kill Anton

在这里插入图片描述
Example
input

4
ANTON
NAAN
AAAAAA
OAANTTON

output

NNOTA
AANN
AAAAAA
TNNTAOOA

在这里插入图片描述

题目大意:

给一个只有 A N T O 的字符串,可以交换相邻的字符,求最大还原步数的改变后的字符串。

思路:

暴力枚举每个字符串的全排列,记录最大的逆序对数,那个字符串就是花最多步数的答案。

cf大佬的代码:

#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
#define int int64_t
typedef tree<pair<int,char>, null_type, less<pair<int,char>>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;
string s;

int check(string s1)
{
	ordered_set os;
	int ans=0;
	deque<int>store[4];
	for(int i=0;i<s1.size();i++)
    {
		os.insert({i,s1[i]});
		if (s1[i]=='A'){store[0].push_back(i);}
		else if (s1[i]=='N'){store[1].push_back(i);}
		else if (s1[i]=='O'){store[2].push_back(i);}
		else{store[3].push_back(i);}
	}
	for(int i=0;i<s.size()-1;i++)
    {
		int x=0;
		if(s[i]=='N'){x=1;}
		else if(s[i]=='O'){x=2;}
		else if(s[i]!='A'){x=3;}
		int y=x;
		x=store[x].front();
		store[y].pop_front();
		ans+=os.order_of_key({x,s[i]});
		auto it=os.find({x,s[i]});
		os.erase(it);
	}
	return ans;
}

signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>s;
        string s1,s2,s3,s4;
        for(auto it:s)
        {
            if(it=='A'){s1+=it;}
            else if(it=='N'){s2+=it;}
            else if(it=='O'){s3+=it;}
            else{s4+=it;}
        }
        vector<string>z{s1,s2,s3,s4};
        string ans;
        int ma=-1;
        do
        {
            string gh;
            for(string it:z){gh+=it;}//以字典序最小的样子开始
            int pres=check(gh);
            if(pres>ma)
            {
                ma=pres;
                ans=gh;
            }
        }while(next_permutation(z.begin(),z.end()));
        cout<<ans<<endl;
    }
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值