CodeForces 474EPillars(线断树区间最大)

来源:互联网 发布:java语言培训哪家好 编辑:程序博客网 时间:2024/06/05 11:55

题目链接

给出n个数字,和最小间隔d。从i能走到j的充要条件就是|aiaj|d,求最长的路径长度并输出路径,有多解输出任意一组路径。
思路就是dp[i]表示以i结尾的最长路径长度,dp[i]<-{pre{dp[j]}里面满足条件且最长的长度} + 1,
这里查找的就可以是区间最大值的查找,因为要记录路径,所以里面还需要最大值对应的原序列中的位置。

const int maxn = 1e5 + 123;struct data {    int len, loc;    data() {}    data(int len,int loc) : len(len), loc(loc) {}    data operator + (const data& rhs) {        return len >= rhs.len ? *this : rhs;    }};struct node {    int l, r;    data v;}p[maxn<<4];void build(int rt, int l, int r) {    p[rt] = node {l, r, data(0, 0)};    if (l == r) return ;    int mid = (l + r) >> 1;    build(lson, l, mid);    build(rson, mid + 1, r);}inline void push_up(int rt) {    p[rt].v = p[lson].v + p[rson].v;}void updata(int rt,int pos, data v) {    if (p[rt].l == pos && p[rt].r == pos) {        p[rt].v = p[rt].v + v;        return ;    }    int mid = (p[rt].l + p[rt].r) >> 1;    if (pos <= mid) updata(lson, pos, v);    if (pos > mid) updata(rson, pos, v);    push_up(rt);}data find(int rt,int L, int R) {    if (L <= p[rt].l && p[rt].r <= R) return p[rt].v;    int mid = (p[rt].l + p[rt].r) >> 1;    if (R <= mid) return find(lson, L, R);    if (L > mid) return find(rson, L, R);    return find(lson, L, R) + find(rson, L, R);}LL h[maxn*5], a[maxn];int m;int nxt[maxn];int n, d;int main(int argc, const char * argv[]){        // freopen("in.txt","r",stdin);    // freopen("out.txt","w",stdout);    // ios::sync_with_stdio(false);    // cout.sync_with_stdio(false);    // cin.sync_with_stdio(false);    cin >> n >> d;    Rep(i, 1, n) {        scanf("%lld", &a[i]);        h[++m] = a[i];        h[++m] = max(0LL, a[i] - d);        h[++m] = a[i] + d;    }    sort(h + 1, h + 1 + m);    m = unique(h + 1, h + 1 + m) - h - 1;    build(1, 1, m);    int res = 0;    int o = 1;    Rep(i, 1, n) {        int l = lower_bound(h + 1, h + 1 + m, max(0LL, a[i] - d)) - h;        int r = lower_bound(h + 1, h + 1 + m, a[i] + d) - h;        data v = find(1, 1, l) + find(1, r, m);        nxt[i] = v.loc;        if (v.len + 1 > res) {            res = v.len + 1;            o = i;        }        int pos = lower_bound(h + 1, h + 1 + m, a[i]) - h;        updata(1, pos, data(v.len + 1, i));    }    vector<int> vec;    printf("%d\n", res);    for (int u = o;u ; u = nxt[u])        vec.push_back(u);    for (int i = res - 1;i >= 0;--i)        printf("%d ", vec[i]);    puts("");    // showtime;    return 0;}
0 0