Codeforces - 985E Pencils and Boxes

题意:

  给定n支铅笔,问能不能分成若干堆,使得每堆数量不小于k且每堆的最大值和最小值之差不大于d。

题解:

  排序。从后往前扫一遍,计算每个点能到达位置的后面位置是否为true。如果有一个为true则该点也为true。用树状数组来维护每个点能到达区间的合法位置和。

#include <bits/stdc++.h>
using namespace std;
int n, k, d;
int a[500005], tre[500005];
int vis[500005];
void add(int x) {
    while(x <= n) {
        tre[x]++;
        x += x&(-x);
    }
}
int sum(int x) {
    int res = 0;
    while(x>0) {
        res += tre[x];
        x -= x&(-x);
    }
    return res;
}
int main() {
    scanf("%d%d%d", &n, &k, &d);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    sort(a+1, a+n+1);
    for(int i = n-k+1; i >= 1; i--) {
        int l = i+k-1, r = upper_bound(a+i, a+n+1, a[i]+d)-a-1;
        if((r>=n) || (r>=l&&sum(r+1)-sum(l)>0)) vis[i] = 1;
        if(vis[i]) add(i);
    }
    if(vis[1]) puts("YES");
    else puts("NO");
}
View Code

猜你喜欢

转载自www.cnblogs.com/Pneuis/p/9070326.html