HDU3016マン・ダウンの説明

HDU3016マン・ダウン

例の問題セグメントツリーコレクション

問題の意味:あるN水平平面における線の部分は、各セグメントは、高さが与えられ、そしてエネルギー左端位置(正または負)、最初の行に、エネルギーと現在のラインセグメント上の最高点100を有していますそしてその後、全ての可能な垂直降下(他のセグメント上に落ちる可能性があり、また地面に落ちることができる)のエネルギー、エネルギーセグメントを得るには、他のライン上に落ち、ゲームが終了した場合ラインからの左または右、秋に地面にゲームを続行します、および現在のエネルギーのスコア。しかし、いずれかの時点では、エネルギー<= 0は、ゲームを終了するために失敗したポジティブなエネルギー、でなければなりません。出力がない場合は地面に落ちた場合は、最大スコアが出力され、-1

私のアプローチはかなり独特であるこの質問(愚かな)

0 EDのライン側との間に接続され、(左右端部が落下セグメントに到達する)、各セグメントは、他の2つのセグメントを指します、地上セグメントに対して仮定さ見ることができる、エッジ長が到着線上にあってもよいですエネルギーは、これは、有向グラフのうち建てたという、ラインはSpfaが最長の道路への0の数が最も多いが、(DPでうまくこの問題を解決するため、実際に)答えが得走りました

上記セグメントが更新続くので、高さに応じて、最低から最高まで、下に覆うことができ、クエリ番号二つのセグメントを見つけることができる:各セグメントから得られるキーは、二つのセグメント約2滝に到達します。現在の行の高さに応じがソートされている、例えば、左端点5までの処理は、線分10の右端点はI、最初の線分ツリーは5,10クエリA、次いで間隔が5--10 iの値に変更されます

#include <bits/stdc++.h>
using namespace std;
inline void read (int &x) {
    char ch = getchar(); int f = 0; x = 0;
    while (!isdigit(ch)) {if (ch == '-') f = 1; ch = getchar();}
    while (isdigit(ch)) x = x * 10 + ch - 48, ch = getchar();
    if (f) x = -x;
}
const int N = 1E5 + 10;
int n, cnt, M, c[N << 2], d[N], to[N][2], vis[N];
struct e {
    int h, l, r, val;
    bool operator < (const e &x) const {return h < x.h;}
} a[N];
#define ls p << 1
#define rs p << 1 | 1
inline void push_down (int p) {
    if (c[p]) c[ls] = c[rs] = c[p], c[p] = 0;
}
int update (int p, int l, int r, int ql, int qr, int val) {
    if (ql <= l && qr >= r) {c[p] = val; return 0;}
    push_down (p);
    int mid (l + r >> 1);
    if (ql <= mid) update (ls, l, mid, ql, qr, val);
    if (qr > mid) update (rs, mid + 1, r, ql, qr, val);
}
int query (int p, int l, int r, int pos) {
    if (l == r) return c[p];
    push_down (p);
    int mid (l + r >> 1);
    return pos <= mid ? query (ls, l, mid, pos) : query (rs, mid + 1, r, pos);
}
inline void Spfa () {
    queue <int> q;
    memset (d, 0xcf, sizeof (d));
    memset (vis, 0, sizeof (vis));
    d[n] = 100 + a[n].val, vis[n] = 1, q.push (n);
    while (!q.empty()) {
        int u = q.front ();
        vis[u] = 0, q.pop ();
        for (int i = 0; i <= 1; ++i) {
            int v = to[u][i];
            if (d[u] + a[v].val > d[v] && d[u] + a[v].val > 0) {
                d[v] = d[u] + a[v].val;
                if (!vis[v]) q.push (v), vis[v] = 1;
            }
        }
    }
}
int main() {
    while (~scanf ("%d", &n)) {
        cnt = M = 0;
        memset (c, 0, sizeof (c));
        for (int i = 1; i <= n; ++i)
            read (a[i].h), read (a[i].l), read (a[i].r), read (a[i].val), M = max (M, a[i].r);
        sort (a + 1, a + n + 1);
        for (int i = 1; i <= n; ++i) {
            int tl = query (1, 1, M, a[i].l), tr = query (1, 1, M, a[i].r);
            to[i][0] = tl, to[i][1] = tr;
            update (1, 1, M, a[i].l, a[i].r, i);
        }
        Spfa ();
        if (d[0] < 0) puts ("-1");
        else printf ("%d\n", d[0]);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/whx666/p/12041543.html