Educational Codeforces Round 44 (Rated for Div. 2)_A-D题解

   A.Chess Placing

很基础的题目,我们只需要按照循序将他们放到1、3、5、7....... 或者 2、4、6、8.......就可以因为棋子不可以进行跳跃,只能一个一个地移动,并且只能顺序移动,所以只用这两种情况,开始错了,因为没有排序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int MAXN = 150;
int a[MAXN];

int main()
{
    int n;
    scanf("%d",&n);
    for(int i =0 ;i < n/2;i ++)
        scanf("%d",&a[i]);
    sort(a,a+n/2);
    int ans = 0,ans2 = 0,tmp = 1,tmp2 = 2;
    for(int i = 0;i < n/2;i ++)
    {
        ans += abs(tmp - a[i]);
        tmp += 2;
    }
    for(int i = 0;i < n/2;i ++)
    {
        ans2 += abs(tmp2 - a[i]);
        tmp2 += 2;
    }
    printf("%d\n",min(ans,ans2));
}

B.Switches ans Lamps

题目意思可以转换为:寻找某一行满足:其中包含1的位置,别的行中在这个位置上也存在是1的情况,这个题也后来被Hacked了,开始不想直接遍历,想找个更快的方法,然后思路就错了,当时思路是:从开始向下寻找,如果某一行中存在的1,前面前几行全部有了,那么也就表示这一行可以去掉。但是后来被hacked了想:如果当前行的后面存在了,但是前面没有满足条件,那么不就错了.....

不得不又循环了一次

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int MAXN = 2100;
int vis[MAXN];
char s[MAXN][MAXN];
int n,m;

int main()
{
    memset(vis,0,sizeof(vis));
    scanf("%d%d",&n,&m);
    for(int i = 0;i < n;i ++)
    {
        scanf("%s",s[i]);
        for(int j = 0;j < m;j ++)
            vis[j] += s[i][j] - '0';
    }
    bool flag = false;
    for(int i = 0;i < n;i ++)
    {
        flag = false;
        for(int j = 0;j < m ;j ++)
        {
            if(s[i][j] == '1' && vis[j] == 1)
            {
                flag = true;
                break;
            }
        }
        if(!flag)
            break;
    }
    if(!flag)
        printf("YES\n");
    else
        printf("NO\n");
}

C.Liebig's Barrels

题目意思是:一共n个木桶,每个木桶由k个木棍组成,给出n*k个木棍,那么木桶最大的盛水量就是最短的木棍决定的,要求木桶盛水量差不能大于l,问最大的总盛水量为多少?

当时想到了很简单的贪心,先选出长度和最短的差距在l范围之内的木棒,然后选取最长的木棒优先,但是写的太麻烦了,自己都把自己绕进去了,最后也没写出来,今天整理了一下思路,发现只要后面的木棒树大于等于k-1个,我们就可以拿出这k-1个然后选择一个前面的木棒中最长的组成一个木桶,依次向前推,就可以了.....

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int MAXN = 1e5+1000;
int n,k,l;
ll a[MAXN];

int main()
{
    while(~scanf("%d%d%d",&n,&k,&l))
    {
        int num = n * k;
        for(int i = 1;i <= num;i ++)
            scanf("%I64d",&a[i]);
        sort(a+1,a+1+num);
        int high = upper_bound(a+1,a+1+num,a[1] + l) - a;
        if(high - 1 < n)
            printf("0\n");
        else
        {
            ll ans = 0;
            int x = num - high + 1,pos = high - 1;
            for(int i = pos;i >= 1;i --)
            {
                if(x >= k-1)
                {
                    ans += a[i];
                    x -= k-1;
                }
                else
                    x++;
            }
            printf("%I64d\n",ans);
        }
    }
}

D.Sand Fortress

题目意思为:有n桶沙子,最左边高h,我们从坐标1开始向后安排沙子高度,相邻高度差不能超过1,最后一个高度必为1,并且第一个高度要小于等于h,求解最少需要安排多少堆可以安排完这个n数量?

思路参考博客:https://www.cnblogs.com/tobyw/p/9070846.html

这里我们可以枚举安排沙子的长度k,并且求解在长度k的条件下,我们可以使用的最大沙子数量,如果小于给出的数量,则在范围后半段计算,相反大于给出的数量,则在范围前半段进行计算

我们怎么计算长度k以及左边栅栏高度确定的请款下,能使用的最大沙子数量呢?


我们所能达到的最大使用量安排图一定是上面这样的,一种情况是:k>h  ,另一种为k <= h 

当k <= h时,使用的数量很好计算:(1+k)*k/2

当k > h 时,我们将图分成两部分:


因为红色部分之外我们要进行分来讨论,当白色部分长度为奇数时,白色部分计算方式为一种,当问偶数时计算方式为一种,这里不再进行展开了,程序中写的非常清楚

但是这样我们还是会错误,因为最大数据为1e18的时候,我们在计算使用数量的时候会查出long long的范围,那么我们就要缩小一下开始二分的两端范围:

最大数值:满足下面情情况:最大数值为:2*sqrt(n) + 1 (假设下面面积为n,那么这个数值就是对应的坐标长度)


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cmath>
#include <algorithm>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
const int MAXN = 5*1e5+1000;
ll n,H;

bool Judge(ll k)//二分长度,求解长度的最大面积,面积大于,返回true,否则返回false
{
    ll area = 0;
    if(k <= H)
        area = (1+k)*k/2;
    else
    {
        area += (H - 1)*H/2;
        ll x =  ceil(double(k - H - 1)/2) + H;  //可以到达的最大高度
        k -= H - 1;
        if(k & 1)  //奇数
            area += x + (x - H) * (H + x - 1);
        else
            area += (x - H + 1) * (x + H);

    }
    //cout<<k<<"  "<<area<<endl;
    return area >= n;
}
ll Solve()
{
    ll l = 1,r = 2*sqrt(n)+1;//这里一定要注意其实范围的选取,否则后面范围很容易超出ll范围
    while(l <= r)
    {
        ll mid = (l+r) >>1;
        if(Judge(mid)) r = mid - 1;
        else l = mid + 1;
    }
    return l;
}
int main()
{
    cin>>n>>H;
    cout<<Solve()<<endl;
    return 0;
}

掉分之旅又要开始了.....这次看来又要掉分了,记录下当前的分数:1256

猜你喜欢

转载自blog.csdn.net/li1615882553/article/details/80408960