题意是数轴上有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; }