UVALive 6834 (线段树)

题意是数轴上有n个商店,分别在1~n,起点是0,要走到n+1,必须每个商店都进去一次.有的商店进入有先后关系,比如要先进第i个商店才能进第j个商店(i>j).求走的最少步数.

既然关系都是逆的,对于每个关系看成一个区间,最终的答案就是n+1+所有区间长度并*2.

然后没看数据量直接上了棵线段树~

#include <bits/stdc++.h>
using namespace std;
#define maxn 1111
#define pl c<<1
#define pr (c<<1)|1
#define lson tree[c].l,tree[c].mid,c<<1
#define rson tree[c].mid+1,tree[c].r,(c<<1)|1

struct node {
    int l, r, mid;
    int sum;
    bool full;
}tree[maxn<<4];
int n, m;

void build_tree (int l, int r, int c) {
    tree[c].l = l, tree[c].r = r, tree[c].mid = (l+r)>>1;
    tree[c].full = 0;
    tree[c].sum = 0;
    if (l == r)
        return ;
    build_tree (lson);
    build_tree (rson);
    return ;
}

void push_down (int c) {
    if (tree[c].l == tree[c].r)
        return ;
    if (tree[c].full == 1) {
        tree[pl].full = tree[pr].full = 1;
        tree[pl].sum = tree[pl].r-tree[pl].l+1;
        tree[pr].sum = tree[pr].r-tree[pr].l+1;
    }
    return ;
}

void update (int l, int r, int c, int x, int y) {
    push_down (c);
    if (l == x && y == r) {
        tree[c].full = 1;
        tree[c].sum = r-l+1;
        return ;
    }
    if (tree[c].mid >= y) {
        update (lson, x, y);
    }
    else if (tree[c].mid < x) {
        update (rson, x, y);
    }
    else {
        update (lson, x, tree[c].mid);
        update (rson, tree[c].mid+1, y);
    }
    tree[c].sum = tree[pl].sum + tree[pr].sum;
}

int main () {
    //freopen ("in", "r", stdin);
    while (scanf ("%d%d", &n, &m) == 2) {
        build_tree (1, n, 1);
        for (int i = 1; i <= m; i++) {
            int l, r;
            scanf ("%d%d", &l, &r);
            if (l >= r)
                continue;
            update (1, n, 1, l+1, r);
        }
        printf ("%d\n", n+1+tree[1].sum*2);
    }
    return 0;
}


你可能感兴趣的:(UVALive 6834 (线段树))