码迷,mamicode.com
首页 > 其他好文 > 详细

hihocoder 1074 字体设计(线段树)

时间:2015-04-01 15:24:52      阅读:157      评论:0      收藏:0      [点我收藏+]

标签:

这题可以把问题转化为,对于一个位置,限制的位置必然是,递增时候,小于他本身,或者递减时候,大于他本身的位置,然后在这个区间中,寻找最大(小)值的位置,这样利用线段树维护即可,对于一个限制位置,可以先把数字离散化掉,然后用权值做节点很容易就处理出来了,然后第二个问题就是普通的rmq问题

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100005;

int n, a[N];
struct Hash {
    int v, id;
    void read(int i) {
        this->id = i;
        scanf("%d", &v);
    }
} h[N];

bool cmp(Hash a, Hash b) {
    return a.v < b.v;
}

#define lson(x) ((x<<1)+1)
#define rson(x) ((x<<1)+2)

struct Node {
    int l, r, Min, Max;
} node[N * 4];

void pushup(int x) {
    node[x].Min = min(node[lson(x)].Min, node[rson(x)].Min);
    node[x].Max = max(node[lson(x)].Max, node[rson(x)].Max);
}

void build(int l, int r, int x = 0) {
    node[x].l = l; node[x].r = r;
    if (l == r) {
        node[x].Min = n + 1;
        node[x].Max = 0;
        return;
    }
    int mid = (l + r) / 2;
    build(l, mid, lson(x));
    build(mid + 1, r, rson(x));
    pushup(x);
}

void add(int v, int val, int x = 0) {
    if (node[x].l == node[x].r) {
        node[x].Max = node[x].Min = val;
        return;
    }
    int mid = (node[x].l + node[x].r) / 2;
    if (v <= mid) add(v, val, lson(x));
    else add(v, val, rson(x));
    pushup(x);
}

int find(int l, int r, int x = 0) {
    if (node[x].l >= l && node[x].r <= r)
        return node[x].Min;
    int mid = (node[x].l + node[x].r) / 2;
    int ans = n + 1;
    if (l <= mid) ans = min(ans, find(l, r, lson(x)));
    if (r > mid) ans = min(ans, find(l, r, rson(x)));
    return ans;
}

int get(int l, int r, int bo, int x = 0) {
    if (node[x].l >= l && node[x].r <= r) {
        if (bo) return node[x].Max;
        return node[x].Min;
    }
    int ans;
    if (bo) ans = 0;
    else ans = n + 1;
    int mid = (node[x].l + node[x].r) / 2;
    if (l <= mid) {
        if (bo) ans = max(ans, get(l, r, bo, lson(x)));
        else ans = min(ans, get(l, r, bo, lson(x)));
    }
    if (r > mid) {
        if (bo) ans = max(ans, get(l, r, bo, rson(x)));
        else ans = min(ans, get(l, r, bo, rson(x)));
    }
    return ans;
}

int v[N], post[N];
int ans[N], an;

int main() {
    while (~scanf("%d", &n)) {
        for (int i = 1; i <= n; i++)
            h[i].read(i);
        sort(h + 1, h + n + 1, cmp);
        for (int i = 1; i <= n; i++)
            a[h[i].id] = i;
        for (int i = 1; i <= n; i++)
            post[a[i]] = i;
        build(1, n);
        add(a[n], n);
        for (int i = n - 1; i >= 1; i--) {
            if (a[i + 1] < a[i]) v[i] = find(a[i] + 1, n);
            else v[i] = find(1, a[i] - 1);
            add(a[i], i);
        }
        for (int i = 1; i <= n; i++)
            add(i, a[i]);
        int u = 1;
        an = 0;
        while (u < n) {
            ans[an++] = u;
            u = post[get(u, v[u] - 1, a[u + 1] > a[u])];
        }
        ans[an++] = u;
        printf("%d\n", an);
        for (int i = 0; i < an; i++)
            printf("%d%c", ans[i], i == an - 1 ? '\n' : ' ');
    }
    return 0;
}


hihocoder 1074 字体设计(线段树)

标签:

原文地址:http://blog.csdn.net/accelerator_/article/details/44806903

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!