hdu 6012 Lotus and Horticulture 打标记

http://acm.hdu.edu.cn/showproblem.php?pid=6012

我们希望能够快速算出,对于每一个温度,都能够算出它在这n颗植物中,能得到多少价值。

那么,对于第i科植物,在[0, L[i] - 1]这些温度中,得到的价值是低温那个价值,同理在[L[i], R[i]]中,和[R[i], mx]中,

那么可以用O(1)打标记的思路去完成。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
map<int, LL>book;
void work() {
    book.clear();
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        int L, R, a, b, c;
        scanf("%d%d%d%d%d", &L, &R, &a, &b, &c);
        book[0] += c;
        book[L << 1] += a - c;
        book[(R << 1) + 1] += b - a;
    }
    LL ans = 0;
    LL tans = 0;
    for (map<int, LL> :: iterator it = book.begin(); it != book.end(); ++it) {
        tans += it->second;
        ans = max(ans, tans);
    }
    printf("%I64d
", ans);
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    int t;
    scanf("%d", &t);
    while (t--) work();
    return 0;
}
View Code

同样可以用线段树完成,就是先把坐标离散了,然后区间更新和上面一样的东西。

线段树维护最大值,seg[cur]表示这课树覆盖的区间,其中某个温度能取得的最大值。

但是我一直wa,不知为何。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
#define lson L, mid, cur << 1
#define rson mid + 1, R, cur << 1 | 1
#define root 1, mx, 1
const int maxn = 500000 + 20;
int L[maxn], R[maxn];
LL a[maxn], b[maxn], c[maxn];
LL add[maxn << 3], seg[maxn << 3];
vector<int>da;
void pushDown(int cur) {
    if (add[cur]) {
        add[cur << 1] += add[cur];
        add[cur << 1 | 1] += add[cur];
        seg[cur << 1 | 1] += add[cur];
        seg[cur << 1] += add[cur];
        add[cur] = 0;
    }
}
void pushUp(int cur) {
    seg[cur] = max(seg[cur << 1], seg[cur << 1 | 1]);
    assert(seg[cur] >= 0);
}
void build(int L, int R, int cur) {
    seg[cur] = add[cur] = 0;
    if (L == R) {
        return;
    }
    int mid = (L + R) >> 1;
    build(lson);
    build(rson);
    pushUp(cur);
}
void upDate(int be, int en, LL val, int L, int R, int cur) {
    if (L >= be && R <= en) {
        seg[cur] += val;
        add[cur] += val;
        return;
    }
    pushDown(cur);
    int mid = (L + R) >> 1;
    if (be <= mid) upDate(be, en, val, lson);
    if (en > mid) upDate(be, en, val, rson);
    pushUp(cur);
}
LL query(int be, int en, int L, int R, int cur) {
    if (L >= be && R <= en) return seg[cur];
    pushDown(cur);
    LL ans = 0;
    int mid = (L + R) >> 1;
    if (be <= mid) ans += query(be, en, lson);
    if (en > mid) ans += query(be, en, rson);
    return ans;
}
void work() {
    da.clear();
    int n;
    scanf("%d", &n);
    da.push_back(-inf);
    da.push_back(-inf);
    da.push_back(-inf);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d%I64d%I64d%I64d", &L[i], &R[i], &a[i], &b[i], &c[i]);
        assert(L[i] <= R[i]);
        if (L[i] > R[i]) swap(L[i], R[i]);
        L[i] *= 2;
        R[i] *= 2;
        da.push_back(L[i]);
        da.push_back(R[i]);
    }
    sort(da.begin(), da.end());
    int gg = da.size();
    for (int i = 3; i < gg; ++i) {
        if (da[i] - da[i - 1] == 2) {
            da.push_back(da[i] - 1);
        }
    }
    sort(da.begin(), da.end());
    int mx = 0;
    for (int i = 1; i <= n; ++i) {
        L[i] = lower_bound(da.begin(), da.end(), L[i]) - da.begin();
        R[i] = lower_bound(da.begin(), da.end(), R[i]) - da.begin();
//        cout << L[i] << " " << R[i] << endl;
        mx = max(mx, R[i] + 2);
    }
//    cout << endl;
    build(root);
    for (int i = 1; i <= n; ++i) {
        upDate(1, L[i] - 1, c[i], root);
        upDate(L[i], R[i], a[i], root);
        upDate(R[i] + 1, mx, b[i], root);
    }
    cout << query(1, mx, root) << endl;
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    int t;
    scanf("%d", &t);
    while (t--) work();
    return 0;
}
View Code

 原来是我离散化错了

一开始的时候,认为[70, 73]  [74, 76]这样,73和74相邻,那么乘以2后,变成146   148,那么相隔2的时候才添加些元素进去,比如添加147进去隔着,这样离散化。

这样有bug(还没想到有什么bug)

现在的思路是:乘以2后,把L[i] + 1和R[i] + 1也放进去,这样就不会有挨着了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
#define lson L, mid, cur << 1
#define rson mid + 1, R, cur << 1 | 1
#define root 1, mx, 1
const int maxn = 500000 + 20;
int L[maxn], R[maxn];
int a[maxn], b[maxn], c[maxn];
LL add[maxn << 3], seg[maxn << 3];
vector<int>da;
void pushDown(int cur) {
    if (add[cur]) {
        add[cur << 1] += add[cur];
        add[cur << 1 | 1] += add[cur];
        seg[cur << 1 | 1] += add[cur];
        seg[cur << 1] += add[cur];
        add[cur] = 0;
    }
}
void pushUp(int cur) {
    seg[cur] = max(seg[cur << 1], seg[cur << 1 | 1]);
}
void build(int L, int R, int cur) {
    seg[cur] = add[cur] = 0;
    if (L == R) {
        return;
    }
    int mid = (L + R) >> 1;
    build(lson);
    build(rson);
    pushUp(cur);
}
void upDate(int be, int en, LL val, int L, int R, int cur) {
    if (L >= be && R <= en) {
        seg[cur] += val;
        add[cur] += val;
        return;
    }
    pushDown(cur);
    int mid = (L + R) >> 1;
    if (be <= mid) upDate(be, en, val, lson);
    if (en > mid) upDate(be, en, val, rson);
    pushUp(cur);
}
void work() {
    da.clear();
    int n;
    scanf("%d", &n);
    da.push_back(-inf);
    da.push_back(-inf);
    da.push_back(-inf);
    for (int i = 1; i <= n; ++i) {
        scanf("%d%d%d%d%d", &L[i], &R[i], &a[i], &b[i], &c[i]);
        L[i] *= 2;
        R[i] *= 2;
        da.push_back(L[i]);
        da.push_back(L[i] + 1);
        da.push_back(R[i] + 1);
        da.push_back(R[i]);
    }
    sort(da.begin(), da.end());
    int mx = 0;
    for (int i = 1; i <= n; ++i) {
        L[i] = lower_bound(da.begin(), da.end(), L[i]) - da.begin();
        R[i] = lower_bound(da.begin(), da.end(), R[i]) - da.begin();
//        cout << L[i] << " " << R[i] << endl;
        mx = max(mx, R[i] + 2);
    }
//    cout << endl;
    build(root);
    for (int i = 1; i <= n; ++i) {
        upDate(1, L[i] - 1, c[i], root);
        upDate(L[i], R[i], a[i], root);
        upDate(R[i] + 1, mx, b[i], root);
    }
    printf("%I64d
", seg[1]);
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    int t;
    scanf("%d", &t);
    while (t--) work();
    return 0;
}
View Code

现在的方法是直接

原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6341684.html