HRBU_20211008训练

目录

 

A - Keanu Reeves

题意:

做法:

B - Number Circle

题意:

做法:

C - Candies!

题意:

做法:

D - Add on a Tree

题意:

做法:


A - Keanu Reeves

题意:

给定字符串长度,这个字符串只包含01,问该怎么去分割这个字符串,才能做到该字符串分割出来的串每一个里面01的个数不相同,注意也有可能不需要分割,因为原来的字符串中01的个数就是不一样的。

做法:

首先,特判点给他排除掉!把原来的串01个数统计一下,然后看看是否满足条件,不满足的话,就直接把第一个拿出来作为一个串,剩下的是一个串,这样就一定保证了每一个分割串中01个数都是不一样的!

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int maxn=2e5+10;
string s;

int main()
{
    ios::sync_with_stdio(false);
    int t,n,num[maxn],maxx=0;
    while(cin>>n)
    {
        int num0=0,num1=0;
        string s;
        cin>>s;
        for(int i=0;i<s.size();i++)
        {
            if(s[i]=='0')
                num0++;
            else
                num1++;
        }
        if(num0!=num1)
            cout<<1<<endl<<s<<endl;
        else
        {
            cout<<2<<endl<<s[0]<<" ";
            for(int i=1;i<s.size();i++)
                cout<<s[i];
            cout<<endl;
        }
    }
    return 0;
}
/**
11000011
*/

B - Number Circle

题意:

给定一个数组,要求把这个数组想象成一个环,也就是说你要把第一个和最后一个连起来,然后你要将这个数组进行重新排序,排序的规则就是任意位置i上的数a[i]都要满足a[i]<a[i-1]+a[i+1],所以a[0]<a[n]+a[1],问你是否可以做到这个排序

做法:

特判点已经出来了,我们仔细想想,你要满足每一位上的都得比他邻居和(该位置的前一位和后一位的和,第一位的已经在题意里说明了)小,那么我们只要保证该位置上的左边那个数比他大,右边那个数比他小,不就保证了邻居和一定大于这个中间数字了吗(也可以是右边那个数比他大,左边的比他小,因为题目说明了有多个答案输出一个即可)因此我们只需要把原数组排序之后先判断一下最大值是否小于他的前两位相加,不满足直接输出-1,否则就把次大数给拿出去,把别的按大到小输出,最后补上次大数就ok了。

WA的两发是被样例干扰了,以为次大数有点是小一点的,其实一样大的也是可以的

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int maxn=2e5+10;
string s;

int main()
{
    ios::sync_with_stdio(false);
    int t,n,a[maxn],sum=0;
    while(cin>>n)
    {
        sum=0;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+n+1);
        if(a[n]>=a[n-1]+a[n-2])
            cout<<"NO"<<endl;
        else
        {
            cout<<"YES"<<endl;
            cout<<a[n];
            int i;
            for(i=n-2;i>=1;i--)
                cout<<" "<<a[i];
            cout<<" "<<a[n-1]<<endl;
        }
    }
    return 0;
}
/**

*/

C - Candies!

题意:

给你一个数组,数组元素都是0~9的数字,数组从头开始,两两相加后成为数组新元素,若新元素大于10,则对10取余然后算做你拿出了一颗糖果,现在给定你一个区间,问在这个区间内你最多可以拿出多少颗糖果(一直循环到只有一个数字为止,这很重要!

做法:

大于10算作一次,因为数组内部元素都是0~9的数,那么区间内所有数字相加的结果和题目中所有操作后得到的数其实就是一个数,因此这个结果是一定,所以算次数就是总和/10就是你能拿出糖果的次数,至于这个区间操作,整个前缀和不就解决时间复杂度的问题了吗,O(q)诶.

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int maxn=2e5+10;
string s;

int main()
{
    ios::sync_with_stdio(false);
    int n;

    while(cin>>n)
    {
        int s[maxn];
        s[0]=0;
        for(int i=1;i<=n;i++)
            cin>>s[i],s[i]+=s[i-1];
        int q,l,r;
        cin>>q;
        while(q--)
        {
            cin>>l>>r;
            cout<<(s[r]-s[l-1])/10<<endl;
        }
    }
    return 0;
}
/**

*/

D - Add on a Tree

题意:

给你构造了一个树的样子(说实话,其实我感觉更像一个无向图)你可以给每一条""都加上一个值(这个""在做法里解释)然后问你是否可以给同一个点的任意一条边都能附上一个不一样的值(同上,一会画图解释)可以的话输出YES,否则输出NO

做法:

先构造一个图先

这样构造出来的树,是不满足条件的,根据题目里的条件,只要某一个节点能通过其他节点到达的一个最终节点(最终节点的概念就是这个节点的度为1这个概念是我自己为了方便做题定义的!别说啥专业知识,你刚就是你对),度就是这个点一共有多少条边,这个样例里2的度是1,1的度是2,3的度是2,4的度是1)图中整条路径就可以表示为2到4的一条"",题目说明了你可以给""加上任意的值,但是一条路上有多条边(也可能就一条边)都是一个值,因此这个树是做不到每一个节点的所有边都是不一样的值的。

接着让我们再看一个能够成功的例子

 首先我们能确定这个树可以分成四条"":5-3,5-4,6-3,6-4。首先赋值要不一样的话,1对于5,6的值可以是不同的,因为5,6都可以作为一条""的起点或者终点,所以可以赋上不同的值,同理可得3,4也是一样的,那唯一存在的变量就是2,1中间的那条,但是2,1中间的那一条边因为同时是两条""的一条边,因此它的值一定与两条""都是不一样的(因为对于的赋值是累加的,不论你给两条路加上的是正数还是负数,这一条边的值保证了与5,6,3,4都是不一样的)

所以能不能赋值成功的关键就在于你赋值的这个""上是不是存在一个点,是只被这一条经过的,也就是说这个点的度就是2,这时你的""的赋值就会导致这个点的所有边都是一个值,不满足题目条件,也就无法构成一个满足条件的树。

#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const int maxn=2e5+10;
string s;

int main()
{
    ios::sync_with_stdio(false);
    int n,u,v;
    int num[maxn],flag=1;
    while(cin>>n)
    {
        memset(num,0,sizeof(num));
        flag=1;
        for(int i=1;i<n;i++)
        {
            cin>>u>>v;
            num[u]++,num[v]++;
        }
        for(int i=1;i<=n;i++)
        {
            if(num[i]==2)
            {
                flag=0;
                break;
            }
        }
        if(flag)
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}
/**

*/

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值