1. 程式人生 > >題解 P2073 【送花】

題解 P2073 【送花】

毒瘤題目

主要思路:線段樹(權值線段樹)

可能很多同學做題之前會看一下題目標籤。

這題的題目標籤就是線段樹平衡樹,然而寫不出來以後,一看題解裡全是STL,一臉茫然,,,

我這裡是一篇正了八經的線段樹解法。

首先我們要看清題:

1.操作的編號一定不能看倒,不能理所當然

2.記得是有這麼一句話:“如果加入的花朵價格已經與花束中已有花朵價格重複,則這一朵花不能加入花束。”一定不能忘了!!!

首先我們想一下如何插入刪除。

我們看題目資料範圍可知,W,C<=1000000,這就很好了,既然我們需要按最大最小排錢數,我們不如直接維護一個以花的價格為權值線段樹所維護資訊的序列。注意:權值線段樹維護的是花的價格!

然後我們維護一個區間裡的最大價格與最小价格,這樣就可以方便2,3操作了。我們不是不能重複加入嗎?那沒關係,我們可以先把每個結點的區間內最大價格和最小价格分別設為-INF和INF,使得只要這個點中有一個數就可以改變之前初始化,那麼我們在每次插入時,記得判斷一下區間最大和區間最小和其中的價格權值是否是初始化狀態就好了,如果不是初始化狀態,就乾脆不改了。

然後就是————

程式碼實現:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define go(i, j, n, k) for (int i = j; i <= n; i += k)
#define fo(i, j, n, k) for (int i = j; i >= n; i -= k)
#define rep(i, x) for (int i = h[x]; i; i = e[i].nxt)
#define mn 1000010
#define inf 2147483647
#define ll long long
#define ld long double
#define fi first
#define se second
#define root 1, 1000000, 1
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define bson l, r, rt
//#define LOCAL
#define mod 
#define Debug(...) fprintf(stderr, __VA_ARGS__)
inline int read(){
    int f = 1, x = 0;char ch = getchar();
    while (ch > '9' || ch < '0'){if (ch == '-')f = -f;ch = getchar();}
    while (ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}
//This is AC head above...
struct tree{
    int minn, maxx, sumw, sumc;
} z[mn << 2];
inline void update(int rt){
    z[rt].minn = min(z[rt << 1].minn, z[rt << 1 | 1].minn);
    z[rt].maxx = max(z[rt << 1].maxx, z[rt << 1 | 1].maxx);
    z[rt].sumw = z[rt << 1].sumw + z[rt << 1 | 1].sumw;
    z[rt].sumc = z[rt << 1].sumc + z[rt << 1 | 1].sumc;
}
inline void build(int l,int r,int rt){
    if(l == r) {
        z[rt].minn = inf;
        z[rt].maxx = -inf;
        z[rt].sumw = z[rt].sumc = 0;
        return;
    }
    int m = (l + r) >> 1;
    build(lson), build(rson), update(rt);
}
inline void modify_add(int l,int r,int rt,int c,int v){
    if(l == r) {
        if(z[rt].minn != inf || z[rt].maxx != -inf || z[rt].sumc){
            return;
        }
        z[rt].minn = z[rt].maxx = c;
        z[rt].sumw = v, z[rt].sumc = c;
        return;
    }
    int m = (l + r) >> 1;
    if(c <= m)
        modify_add(lson, c, v);
    else
        modify_add(rson, c, v);
    update(rt);
}
inline void modify_del(int l,int r,int rt,int c){
    if(l == r) {
        z[rt].minn = inf, z[rt].maxx = -inf;
        z[rt].sumw = z[rt].sumc = 0;
        return;
    }
    int m = (l + r) >> 1;
    if(c <= m)
        modify_del(lson, c);
    else
        modify_del(rson, c);
    update(rt);
}
int vis[mn], tot, s;
int main(){
    build(root);
    s = read();
    while(s != -1){
        if(s == 1){
            int x = read(), y = read();
            modify_add(root, y, x);
        }else if(s == 2){
            int maxx = z[1].maxx;
            modify_del(root, maxx);
        }else{
            int minn = z[1].minn;
            modify_del(root, minn);
        }
        s = read();
    }
    printf("%d %d\n", z[1].sumw, z[1].sumc);
#ifdef LOCAL
    Debug("\nMy Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
    return 0;
}