codeforces 985 E. Pencils and Boxes (dp 树状数组)
2 seconds
256 megabytes
standard input
standard output
Mishka received a gift of multicolored pencils for his birthday! Unfortunately he lives in a monochrome world, where everything is of the same color and only saturation differs. This pack can be represented as a sequence a1, a2, ..., an of n integer numbers — saturation of the color of each pencil. Now Mishka wants to put all the mess in the pack in order. He has an infinite number of empty boxes to do this. He would like to fill some boxes in such a way that:
- Each pencil belongs to exactly one box;
- Each non-empty box has at least k pencils in it;
- If pencils i and j belong to the same box, then |ai - aj| ≤ d, where |x| means absolute value of x. Note that the opposite is optional, there can be pencils i and j such that |ai - aj| ≤ d and they belong to different boxes.
Help Mishka to determine if it's possible to distribute all the pencils into boxes. Print "YES" if there exists such a distribution. Otherwise print "NO".
The first line contains three integer numbers n, k and d (1 ≤ k ≤ n ≤ 5·105, 0 ≤ d ≤ 109) — the number of pencils, minimal size of any non-empty box and maximal difference in saturation between any pair of pencils in the same box, respectively.
The second line contains n integer numbers a1, a2, ..., an (1 ≤ ai ≤ 109) — saturation of color of each pencil.
Print "YES" if it's possible to distribute all the pencils into boxes and satisfy all the conditions. Otherwise print "NO".
- 6 3 10
7 2 7 7 4 2
- YES
- 6 2 3
4 5 3 13 4 10
- YES
- 3 2 5
10 16 22
- NO
In the first example it is possible to distribute pencils into 2 boxes with 3 pencils in each with any distribution. And you also can put all the pencils into the same box, difference of any pair in it won't exceed 10.
In the second example you can split pencils of saturations [4, 5, 3, 4] into 2 boxes of size 2 and put the remaining ones into another box.
【题意】
给$$$n$$$个数,可以放到若干个盒子里,要求每个盒子至少有$$$k$$$个数,并且每个盒子中最大和最小的数差值不超过$$$d$$$。问是否有合理的方案来分配。
【分析】
因为要比较差值,所以按从小到大对输入排序,如果$$$a_i$$$和$$$a_j$$$已经放到同一个盒子里了,那么大小介于$$$a_i$$$和$$$a_j$$$之间的数也一定可以放到这个盒子中。
由于上述的性质,每个盒子都应该装$$$a_i$$$~$$$a_j$$$的全部数。因为$$$a_i$$$和$$$a_j$$$是离其他数最近的数,如果现在的分配不可行,一定是先把$$$a_i$$$或$$$a_j$$$重新划分给相邻的盒子,成为新的区间端点,而整个方案依然的连续的;而如果$$$a_i$$$和$$$a_j$$$不能分配给其他盒子,那么内部的其他数也一定不行。从另一方面来说,如果把一个$$$a_i$$$~$$$a_j$$$中的一个$$$a_x$$$拿出去,最终形成了可行方案,那么一定可以通过把$$$a_x$$$与$$$a_i$$$或$$$a_j$$$交换,使方案依然可行而且每个盒子中变成连续的区间。
连续分配说明完了,之后都把盒子当作区间来处理,问题转化为:把1~n个数分为几个连续的区间,使的每个区间$$$[a_i, a_j]$$$的$$$a_j-a_i \le d, j-i \ge k$$$。
预处理:对于每个$$$a_i$$$一定有一个最大的$$$a_j$$$,用二分查找得到其下标,并把$$$a_j$$$下一个位置也就是$$$j+1$$$记录到$$$right[i]$$$ (下面会介绍) 中。
如果一个盒子是$$$[a_i, a_j]$$$那么下一个盒子的起点就是$$$a_{j+1}$$$。可以把从$$$a_i$$$到$$$a_{j+1}$$$看成一次转移,这样重复下去,如果最后刚好能到达数列的末端,那么从$$$a_i$$$开始就是可行的,$$$a_i$$$就是能到末端的点。这个时候$$$right[i]$$$数组就发挥作用了,对于$$$a_i$$$,它能转移到的起点有 $$$a_{i+k}, a_{i+k+1}, ...,a_{right[i]}$$$;
dp可以采取从后向前的顺序。在考虑$$$a_i$$$作为起点时,它可以转移到的点都在它后面,所以$$$[a_{i+k}, a_{right[i]}]$$$都处理过了,只要其中包含末端,或者能到末端的点,那么$$$a_i$$$也是能到达末端的点;如果区间不存在,或者不包含能到末端的点,那么$$$a_i$$$就不能到达末端。这样从后向前处理完所有点以后,起点能否到达末端就是答案的YES/NO。
如果用0表示无法到达末端,1表示能到达末端,那么转移方程就是:
$$$$$$dp[i]= (\sum_{j=i+k}^{right[i]} dp[j]) \gt 0$$$$$$
起始状态为$$$dp[n]$$$=$$$1$$$。
【注意】
使用树状数组来完成求和操作,下标的起点必须是1。
- #include<stdio.h>
- #include<algorithm>
- using std::sort;
- #define N_max 500005
- int ipt[N_max], right[N_max];
- int n, k, d;
- int cmpv(int t1, int t2) {
- return t1 < t2;
- }
- void cal_r(int i) {
- if (right[i] != 0)return;
- int l = i, r = n + 1, m;
- while (l + 1<r)
- {
- m = (l + r) / 2;
- if (ipt[m] <= ipt[i] + d)l = m;
- else r = m;
- }
- right[i] = r;
- }
- struct BIT {
- int c[N_max] = { 0 };//每个ci维护的都是1~i的最新和
- int lowbit[N_max] = { 0 };
- int n;
- BIT(int _n = N_max) {
- n = _n;
- for (int i = 1; i <= N_max; ++i) lowbit[i] = (i&(-i));
- }
- void newBIT(int _n) {
- n = _n;
- for (int i = 1; i <= n; ++i)
- c[i] = 0;
- }
- //更新时向右(上)更新
- void update(int x, int num) {
- while (x <= n) {
- c[x] += num;
- x += lowbit[x];
- }
- }
- //求和时向左(下)依次求和
- int getsum(int x) {
- int s = 0;
- while (x > 0) {
- s += c[x];
- x -= lowbit[x];
- }
- return s;
- }
- }bit;
- int main() {
- scanf("%d %d %d", &n, &k, &d);
- bit.newBIT(n+1);
- for (int i = 1; i <= n; ++i)
- scanf("%d", ipt + i);
- sort(ipt + 1, ipt + n + 1, cmpv);
- int state;
- //初始状态为只有末端可以到达末端
- bit.update(n + 1, 1);
- //计算right[i]
- for (int i = 1; i <= n; ++i)
- cal_r(i);
- //从后向前dp
- for (int i = n; i >= 1; --i)
- {
- if (i + k - 1 <= n)//至少存在一个
- {
- //使用树状数组判断区间内是否有不为0 的值
- state = (bit.getsum(right[i]) - bit.getsum(i + k - 1)) > 0;
- bit.update(i, state);
- }
- }
- state = bit.getsum(1);
- printf("%s", state == 1 ? "YES" : "NO");
- return 0;
- }
codeforces 985 E. Pencils and Boxes (dp 树状数组)的更多相关文章
- 树形DP+树状数组 HDU 5877 Weak Pair
//树形DP+树状数组 HDU 5877 Weak Pair // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值 // 这道题要离散化 #i ...
- bzoj 1264 [AHOI2006]基因匹配Match(DP+树状数组)
1264: [AHOI2006]基因匹配Match Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 793 Solved: 503[Submit][S ...
- 【bzoj2274】[Usaco2011 Feb]Generic Cow Protests dp+树状数组
题目描述 Farmer John's N (1 <= N <= 100,000) cows are lined up in a row andnumbered 1..N. The cows ...
- 奶牛抗议 DP 树状数组
奶牛抗议 DP 树状数组 USACO的题太猛了 容易想到\(DP\),设\(f[i]\)表示为在第\(i\)位时方案数,转移方程: \[ f[i]=\sum f[j]\;(j< i,sum[i] ...
- CodeForces - 597C Subsequences 【DP + 树状数组】
题目链接 http://codeforces.com/problemset/problem/597/C 题意 给出一个n 一个 k 求 n 个数中 长度为k的上升子序列 有多少个 思路 刚开始就是想用 ...
- codeforces 597C C. Subsequences(dp+树状数组)
题目链接: C. Subsequences time limit per test 1 second memory limit per test 256 megabytes input standar ...
- Codeforces 1096F(dp + 树状数组)
题目链接 题意: 对于长度为$n$的排列,在已知一些位的前提下求逆序对的期望 思路: 将答案分为$3$部分 $1.$$-1$与$-1$之间对答案的贡献.由于逆序对考虑的是数字之间的大小关系,故假设$- ...
- Codeforces 909 C. Python Indentation (DP+树状数组优化)
题目链接:Python Indentation 题意: Python是没有大括号来标明语句块的,而是用严格的缩进来体现.现在有一种简化版的Python,只有两种语句: (1)'s'语句:Simple ...
- Codeforces 1085G(1086E) Beautiful Matrix $dp$+树状数组
题意 定义一个\(n*n\)的矩阵是\(beautiful\)的,需要满足以下三个条件: 1.每一行是一个排列. 2.上下相邻的两个元素的值不同. 再定义两个矩阵的字典序大的矩阵大(从左往右从上到下一 ...
随机推荐
- python--模块之random随机数模块
作用是产生随机数 import random random.random:用于生成一个0--1的随机浮点数. print(random.random())>>0.3355102133472 ...
- 成都Uber优步司机奖励政策(1月17日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 说说CakePHP的关联模型之一 基本关联
一个无论多么复杂的程序,拆开看无非是三种逻辑结构的组合:顺序结构.条件结构和循环结构. 类似的,数据库中表与表的之间的关联无外乎四种:一对一.一对多.多对一和多对多. CakePHP的模型层中定义了四 ...
- jQuery tableExport导出 excel
上篇写的是jQuery 导出word,就试试导出excel.看见网上写的很乱,我这就把我写的整理下来,有部分来自网上capy 1. js文件的引用 <script type="te ...
- Mate20兼容性如何?WeTest带你抢先测!
自从九月份 iPhone XS 系列发布后,WeTest团队迅速入库了iPhone XS和iPhone XR设备,十月份国内巨头华为也重磅推出了一款“Mate 20”设备,让下半年的国内手机市场又热闹 ...
- json模块使用总结——Python
# 原创文章,未经允许请勿转载 通过Python的json模块,可以将字符串形式的json数据转化为字典,也可以将Python中的字典数据转化为字符串形式的json数据. 之前使用这个模块时,都是随用 ...
- apache+php+mysql开发环境搭建
一.Apache 因为Apache官网只提供源代码,如果要使用必须得自己编译,这里我选择第三方安装包Apache Lounge. 进入Apachelounge官方下载地址:http://w ...
- hdu2094产生冠军(思维题)
产生冠军 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- QT 标题栏隐藏可拖拽
这个也是我网上找到了 为了方便,记录一下 void mousePressEvent(QMouseEvent *e); void mouseMoveEvent(QMouseEvent *e); void ...
- 微服务框架Dubbo与Springcloud的区别
微服务框架Dubbo与Springcloud的区别 微服务主要的优势如下: 1.降低复杂度 将原来偶合在一起的复杂业务拆分为单个服务,规避了原本复杂度无止境的积累.每一个微服务专注于单一功能,并通过定 ...