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

A. Chess Placing(模拟)

题目链接:点击打开链接

题目大意:现在有长度为n的格子,n个格子分为两类,奇数格子和偶数格子。

给出n/2个元素的队列,给出他们当前在n个格子中的位置,他们能左右移动,但一个格子只能由一个元素,问最少移动多少次将所给出的所有元素移动到奇数格子或是全部移动到偶数格子。

题目思路:观察的题目的数据范围100,暴力计算奇数和偶数格子的最少步数比较即可

#include <bits/stdc++.h>

using namespace std;

int main() {
	int n;
	cin >> n;
	vector<int> pos(n / 2);
	for (int i = 0; i < n / 2; ++i)
		cin >> pos[i];
	sort(pos.begin(), pos.end());
	
	int ans1 = 0, ans2 = 0;
	for (int i = 0; i < n / 2; ++i) {
		ans1 += abs(pos[i] - (i * 2 + 1));
		ans2 += abs(pos[i] - (i * 2 + 2));
	}
	
	cout << min(ans1, ans2) << endl;
	
	return 0;
}

B. Switches and Lamps(模拟)

题目链接:点击打开链接

题目大意:n个开关,m栈灯,每个开关控制一些灯。问删除一个开关,能否用剩下的n-1个开关控制所有的灯

题目思路:记录每盏灯会被多少开关控制

然后查找是否有一栈灯只被一个开关控制

#include <bits/stdc++.h>
using namespace std;
#define maxn 5000
#define LL long long
int n,m;
int a[maxn][maxn];
int num[maxn];
char s[maxn];
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",&s[1]);
        for(int j=1;j<=m;j++)
        {
            a[i][j]=s[j]-'0';
            num[j]+=a[i][j];
        }
    }

    int ok=1;
    for(int i=1;i<=n;i++)
    {
        ok=1;
        for(int j=1;j<=m;j++)
        {
            if(a[i][j]==1&&num[j]==1)
            {
                ok=0;
                break;
            }
        }
        if(ok)break;
    }
    if(ok)printf("YES\n");
    else printf("NO\n");
    return 0;
}

C. Liebig's Barrels(贪心)

题目链接:点击打开链接

题目大意:给出n个木板,告诉你m个木板可以组成一个桶,桶的装水高度由最短木板的长度决定,并且所有组成的木桶他们的最短木板的两两高度差小于等于l。

求出所有桶的最大装水量和,如果不能组成n个桶,则输出0

题目思路:这题主要是一个贪心的策略。

一开始,将所有ai按非递减顺序排序。

然后计算从第一个最短的木板开始有多少个木板他们的两两高度差满足小于等于l的要求,假设前面有k个木板满足,k如果小于m个直接输出0.

如果k大于等于m,他们肯定是有结果的,接下来就是用贪心的策略来让结果尽可能的大。

因为一个木桶的体积由最小木板决定,所有前面的木桶尽量的选取较短的木板拼凑,让之后的最短木板尽可能的大。

但是注意,m个木桶的最短木板只能在之前找到的前k个木板中查找,我们的贪心就是尽可能的剔除掉k个中较短的,留下较长的。

#include <bits/stdc++.h>
using namespace std;
#define maxn 500000
#define LL long long
int n,k,l;
int a[maxn];
int main()
{
    cin>>n>>k>>l;
    int len=n*k;
    for(int i=1;i<=len;i++)cin>>a[i];
    sort(a+1,a+len+1);
    int num=1;
    for(int i=2;i<=len;i++)
    {
        if(a[i]-a[1]<=l)
        {
            num=i;
        }
        else break;
    }
    int del=num-n;
    if(del<0)
    {
        printf("0\n");
        return 0;
    }
    LL sum=0;
    int cnt=0;
    for(int i=1;i<=num;i++)
    {
        cnt++;
        if(cnt>k)cnt=1;
        if(cnt==1&&del)
        {
            sum+=a[i];
        }
        else if(cnt>1&&del)
        {
            del--;
        }
        else if(del==0)
        {
            sum+=a[i];
        }
    }
    printf("%I64d\n",sum);
    return 0;
}
D. Sand Fortress

题目链接:点击打开链接

题目大意:

题目思路:让我们考虑一下最优的答案,总是看起来像h1 ≤ h2 ≤ ... ≤ hk ≥ hk + 1 ≥ ...

k将是一个最大高度的柱子的最左边的位置。我们将大量使用从1到hk的所有整数在这个序列中出现在k的右边。

如果您能够构造任何答案,那么很容易将其重新安排到这个模式:选择最左边的k,排序[1..(k - 1)在非递减的顺序和[k + 1.]中,在非递增的顺序中。排序序列也是有效的。

让高度k的金字塔是一个有效的城堡,它正好占据了2k - 1个连续点,1 = h1 < h2 <…建造它需要的是k2砂包。

最后,可以使用以下算法计算出答案:

1.找出最大值k,在中,其中h1 = min(k, H)。解这个方程或者只做二分查找;

2.输出被截断的金字塔的宽度,加上它将用来分配剩余沙袋的最小数量的额外柱子。

#include <bits/stdc++.h>

#define forn(i, n) for (int i = 0; i < int(n); i++)

typedef long long li;

using namespace std;

const int INF = 2e9;
li n, h;

bool check(li maxh){
	li k = min(h, maxh);
	li cnt = maxh * maxh - k * (k - 1) / 2;
	return (cnt <= n);
}

li get(li maxh){
	li k = min(h, maxh);
	li cnt = maxh * maxh - k * (k - 1) / 2;
	li len = (2 * maxh - 1) - (k - 1);
	n -= cnt;
	return len + (n + maxh - 1) / maxh;
}

int main() {
	scanf("%lld%lld", &n, &h);
	li l = 1, r = INF;
	
	while (l < r - 1){
		li m = (l + r) / 2;
		
		if (check(m))
			l = m;
		else
			r = m;
	}
	
	printf("%lld\n", check(r) ? get(r) : get(l));
	return 0;
}

E. Pencils and Boxes

题目链接:点击打开链接

题目大意:N 个数,要求分成任意堆,要求每一堆只要有K个,同一堆中任意数之间差值不能超过d;

题目思路:用树状数组。排一下序然后从后面开始找,以当前数为最小值看能否成堆,要成堆的话要求i+k,到第一个大于a[i]+d的位置之间有能够成堆的位置。(这里判断的时候树状数组一减看是否大于0就可以了)注意初始化时在n+1的位置加1.

#include <bits/stdc++.h>
 
using namespace std;
 
#define forn(i, n) for(int i = 0; i < int(n); i++) 

const int N = 500 * 1000 + 13;

int f[N];

void upd(int x){
    for (int i = x; i < N; i |= i + 1)
        ++f[i];
}

int sum(int x){
    int res = 0;
    for (int i = x; i >= 0; i = (i & (i + 1)) - 1)
        res += f[i];
    return res;
}

int get(int l, int r){
	if (l > r) return 0;
	return sum(r) - sum(l - 1);
}

int main(){
	int n, k, dif;
	scanf("%d%d%d", &n, &k, &dif);
	vector<int> a(n);
	forn(i, n)
		scanf("%d", &a[i]);
	sort(a.begin(), a.end());
	
	vector<int> dp(n + 1, 0);
	
	dp[0] = 1;
	upd(0);
	
	int l = 0;
	forn(i, n){
		while (l < i && a[i] - a[l] > dif)
			++l;
		dp[i + 1] = (get(l, i - k + 1) >= 1);
		if (dp[i + 1]) upd(i + 1);
	}
	
	puts(dp[n] ? "YES" : "NO");
}


剩下的之后更新。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值