codeforces 985E Pencils and Boxes

题意:

把一个数组分成若干组,保证每组的size >= k并且一组中任意两个数字的差的绝对值 <= d,问存不存在这样的分法。

思路:

线性dp。

用dp[i]表示前i个数是否有分法。

设j为满足a[i] - a[j] <= d的最小的a[j]的下标,那么dp[i]就可以从dp[j-1] ~ dp[i-k]转移,j可以二分得到。

首先一定得满足i - k,因为至少有k个数字;

假设前j-1个数字有分法,那么当j - 1 <= i - k的时候,说明第j到第i个数字至少有k个数字并且a[i] - a[j] <= d。

但是从j-1到i-k扫一遍要花费O(n)的时间,所以需要维护一个前缀和,判断的时候只需要j -1 <= i - k 并且pre[i-k] - pre[j-2] > 0,就说明从j - 1到i - k这个区间内有满足的分法。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 5e5 + 10;
 6 int a[N];
 7 int dp[N];
 8 int pre[N];
 9 int main()
10 {
11     int n,k,d;
12     scanf("%d%d%d",&n,&k,&d);
13     for (int i = 1;i <= n;i++)
14     {
15         scanf("%d",&a[i]);
16     }
17     sort(a+1,a+n+1);
18     if (a[k] - a[1] <= d) dp[k] = 1;
19     pre[k] = dp[k] + 1;
20     dp[0] = 1;
21     pre[0] = 1;
22     for (int i = k + 1;i <= n;i++)
23     {
24         int en = i - k;
25         int l = 1,r = i;
26         while (r - l > 1)
27         {
28             int mid = (l + r) >> 1;
29             if (a[i] - a[mid] <= d) r = mid;
30             else l = mid + 1;
31         }
32         while (r > 1 && a[i] - a[r-1] <= d) r--;
33         int st = r;
34         if (st == 1) dp[i] = 1;
35         else if (st-1 <= en) if (pre[en] - pre[st-2] > 0) dp[i] = 1;
36         pre[i] = pre[i-1] + dp[i];
37     }
38     if (dp[n]) puts("Yes");
39     else puts("No");
40     return 0;
41 }

原文地址:https://www.cnblogs.com/kickit/p/9070868.html

时间: 2024-10-07 07:56:45

codeforces 985E Pencils and Boxes的相关文章

Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://codeforces.com/contest/985/problem/E Description Mishka received a gift of multicolored pencils for his birthday! Unfortunately he lives in a monochrome w

Codeforces 985 E - Pencils and Boxes

E - Pencils and Boxes 思路: dp 先排个序,放进一个袋子里的显然是一段区间 定义状态:pos[i]表示小于等于i的可以作为(放进一个袋子里的)一段区间起点的离i最近的位置 显然,初始状态:pos[i] = 1,1 <= i <= k 状态转移: pos[i+1] = i+1 ,如果 a[i] - a[pos[i-k+1]] <= d , 因为在这种情况下pos[i-k+1] 到 i 可以放进一个袋子里,那么i+1就可以作为新的起点了 pos[i+1] = pos[

Educational Codeforces Round 44 (Rated for Div. 2)+E. Pencils and Boxes+树状数组

题目链接:E. Pencils and Boxes 题意:N 个数,要求分成任意堆,要求每一堆只要有K个,同一堆中任意数之间差值不能超过d; 题解:用树状数组.排一下序然后从后面开始找,以当前数为最小值看能否成堆,要成堆的话要求i+k,到第一个大于a[i]+d的位置之间有能够成堆的位置.(这里判断的时候树状数组一减看是否大于0就可以了)注意初始化时在n+1的位置加1. 1 #include<bits/stdc++.h> 2 #include <iostream> 3 #includ

CodeForces 551C GukiZ hates Boxes

题目链接:CodeForces 551C GukiZ hates Boxes 解题思路: 题目要求最短时间,因此我们可以先考虑最长时间,最长时间一定是一个学生从开始走到结束,每走到一处就把该处箱子搬空,所以最长时间等于走到最后一个有箱子格子的步数ed加箱子总数sum. 接下来二分所需时间,直接搜索最短时间,每次都对假设时间进行判断.每次判断都从第一格开始,因为要搬空一个格子的箱子一定需要学生走到该处,同时所有学生可以同时移动,所以从头到尾判断要搬空该处需要多少学生,再与有的学生数量进行比较. 代

Educational Codeforces Round 44 - E. Pencils and Boxes

标签 : DP 题目链接 http://codeforces.com/contest/985/problem/E 题意 把\(n\)个数分成多组,使得每组包含至少\(k\)个元素,且每组中的任意两个元素之差不超过\(d\) 分析 很巧妙的DP 我们使用dp[i]来表示(如果不存在i+1~n个元素的时候)前i个能否满足题目条件放入boxes中. dp[i]为true当且仅当存在一个j满足 \[ \left\{ \begin{aligned} a[j+1] \geq a[i]-d \\ dp[j]=

【CodeForces 990A】Commentary Boxes

题目链接 luogu & CodeForces 题目描述 Berland Football Cup starts really soon! Commentators from all over the world come to the event. Organizers have already built nn commentary boxes. mm regional delegations will come to the Cup. Every delegation should get

Codeforces 551C GukiZ hates Boxes(二分)

Problem C. GukiZ hates Boxes Solution: 假设最后一个非零的位置为K,所有位置上的和为S 那么答案的范围在[K+1,K+S]. 二分这个答案ans,然后对每个人尽量在ans时间内搬最多的砖.可以得出至少需要多少个人才能搬完.这个可以在O(n)的时间内利用贪心得到 只要判断需要的人数是否小于等于实际的人数就好了 时间复杂度O(nlogS) #include <bits/stdc++.h> using namespace std; const int N = 1

Codeforces 821C Okabe and Boxes(模拟)

题目大意:给你编号为1-n的箱子,放的顺序不定,有n条add指令将箱子放入栈中,有n条remove指令将箱子移除栈,移出去的顺序是从1-n的,至少需要对箱子重新排序几次. 解题思路:可以通过把栈清空表示已经排过序了,如果下一次remove时栈为空,说明已经排序过且没有新的箱子放入,因为题目确保在需要删除之前添加每个箱子,所以肯定栈顶的箱子是我们所需要的.如果栈不为空则判断栈顶箱子序号是否是我们需要的,不是则重新排序,用清空栈来表示. 这里用数字模拟了栈. 1 #include<iostream>

Codeforces 551C - GukiZ hates Boxes(二分加贪心)

题意: 就是n个学生帮助教授搬箱子, 箱子分成m 堆, 每个学生每秒可以选择的两个操作 操作1,为从i堆迈向第i+1堆, 操作2,从i-1堆箱子中帮忙抱走一个箱子 问抱走所有箱子的最少时间为多少, 每个学生每秒可以同时行动 题解: 二分时间   然后再当前时间下,一个一个派出所有的学生,使其走到他能走的最远距离 代码: #include<stdio.h> int flag, value[100005], value2[100005], n, m; void find(long long int