Educational Codeforces Round 75 (Rated for Div. 2)

题目链接:http://codeforces.com/contest/1251

B. Binary Palindromes

题意:告诉你n个含有数字0和1的串,你可以进行操作,交换两个位置的数字,问你通过操作后最多可以得到多少个回文串

思路:数字只有0和1,那就好办了,在n个字符串中,如果字符串的长度为奇数,那么中间那个位置随便放,如果字符串的长度为偶数的话,那么只有成对的1和0才能组成回文数,所以如果这n个串中只要含有一个串是奇数串的话那么组成的回文串最多为n,如果n个串全是偶数,然后你对1和0的个数进行判断,如果是偶数(即成对),那么组成的回文串为n,如果1和0为奇数,那么就有一个串不能组成回文串,就是n-1个回文串

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
 
using namespace std;
int v[5];
char s[1005];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(v,0,sizeof(v));
        int n;
        scanf("%d",&n);
        int flog=0;
        for(int a=1;a<=n;a++)
        {
            scanf("%s",s);
            int m=strlen(s);
            if(m%2)
                flog=1;
          for(int a=0;a<m;a++)
          {
            if(s[a]=='0')
            {
                v[0]++;
            }
            else
                v[1]++;
          }
          memset(s,0,sizeof(s));
        }
        if(flog==1)
        {
            printf("%d\n",n);
        }
        else
        {
            if(v[1]%2)
            {
                printf("%d\n",n-1);
            }
            else
            {
                printf("%d\n",n);
            }
        }
 
    }
    return 0;
}

C. Minimize The Integer

题意:就是给你t个串,对于每个串,如果相邻的两个数字是一奇一偶的话,那么这两个数字就可以交换位置,题目让你求交换过后这串数字最小的值是多少

思路:对于串中的每一个数字,如果它是奇数(偶数)的话,无论它怎么交换,之前在它前面的奇数(偶数)还是在它前面,所以你可以把奇数和偶数分离出来,顺序还是和它在原串中的奇数(偶数)顺序不变,然后进行偶数和奇数比较,小的就先输出来

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
const int maxn=300005;
char s[maxn];
int p[maxn],q[maxn];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(s,0,sizeof(s));
        memset(p,0,sizeof(p));
        memset(q,0,sizeof(q));
        scanf("%s",s);
        int m=strlen(s);
        int k=0,l=0;
        for(int a=0;a<m;a++)
        {
            if((s[a]-'0')%2)
            {
                p[k++]=s[a]-'0';
            }
            else
            {
                q[l++]=s[a]-'0';
            }
        }
        int i=0,j=0;
        for(int a=0;a<m;a++)
        {
            if(i==k)
            {
                for(int b=j;b<l;b++)
                {
                    printf("%d",q[b]);
                }
                break;
            }
            if(j==l)
            {
                for(int b=i;b<k;b++)
                {
                    printf("%d",p[b]);
                }
                break;
            }
            if(p[i]>=q[j])
            {
                printf("%d",q[j]);
                j++;
            }
            else
            {
                printf("%d",p[i]);
                i++;
            }
        }
        printf("\n");
    }
    return 0;
}

D. Salary Changing

题意:给你n个员工和你手中的最大资金,接下来n行给出你每个员工发的工资范围,在你手中的资金范围内,给n名员工发工资,然后对他们的工资排序,让你求工资在最中间的那个人的工资最大是多少

思路:用二分进行枚举。如果工资最小值大于枚举的工资,那么就加上这个工资最小值,并且记录大于等于枚举工资的人数。如果工资最小值小于枚举的工资,并且最大值大于等于枚举的工资而且大于枚举工资的人数不够的话,就加上枚举的工资然后人数+1,然后记录一下大于枚举工资的人数。如果工资最大值小于所枚举的工资,那么直接就加上工资的最小值。最后进行判断

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+5;
struct lll
{
    int l,r;
}v[maxn];
bool uuu(lll a,lll b)
{
    return a.l<b.l;
}
bool twopoint(ll mid,int n,ll m)
{
    int ans=n/2+1;
    int ant=0;
    ll cost=0;
    for(int a=n-1;a>=0;a--)
    {
        if(v[a].l>=mid)
        {
            cost+=v[a].l;
            ant++;
        }
        else
        {
            if(ant<ans&&v[a].r>=mid)
            {
                cost+=mid;
                ant++;
            }
            else
            {
                cost+=v[a].l;
            }
        }
    }
    if(cost<=m&&ant>=ans)
    {
        return true;
    }
    return false;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll m;
        int n;
        scanf("%d%lld",&n,&m);
        for(int a=0;a<n;a++)
        {
            scanf("%d%d",&v[a].l,&v[a].r);
        }
        sort(v,v+n,uuu);
        ll l=1,r=m,mid;
        while(l<=r)
        {
            mid=(l+r)/2;
            if(twopoint(mid,n,m))
            {
                l=mid+1;
            }
            else
            {
                r=mid-1;
            }
        }
        printf("%lld\n",r);
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值