P4087 [USACO17DEC]Milk Measurement

##这题真是恶心,很久没有一道题搞大半天了。

这个题稍微分析一下,首先发现日期的乱序根本就是出题人闲得无聊,排序一下搞定。
然后,不难看出我们肯定需要维护牛的产奶量的最大值,这个倒是有很多方法搞,可以用平衡树或者离散化 + 线段树什么的。
可是这是不够的。只维护某一天的最大值不能算出是否应该更新相框。
怎么办呢?我们先来考虑有哪几种情况。




在这个图中,max线表示除去这头牛,其他牛的最大产奶量,箭头表示当前的牛产奶量的变化。

红色打勾的情况是需要更新答案的。


(7)号和(8)号可以放到一起。它们的共同特征是 修改后的值比当前的最大值小,而且之前它是第一名。 **

我把这种情况叫做王者的陨落

至于(1, 2, 3, 6)号就比较麻烦,因为我们不好直接把他们和(4, 5)号区分开来。仔细观察,发现我们要区分的话,还需要维护
产奶量为特定值的牛的个数
我这儿选用了map来维护这个玩意儿。
所以此时,(4, 5)号的特征就变成了
上一次最大值和这一次最大值都是它,而且没有人跟它现在一样大**。
然后,(1 - 6)号的共性是现在这头牛的产奶量是最大(之一)的,于是可以用排除法筛选出(1, 2, 3, 6)号。

我把(4, 5)号叫做王者的余裕

分析到这,就可以动手敲键盘啦!

#include <map>
#include <vector>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int, int> P;
const int MAXN = 1e6 + 20;
inline int read()
{
    int x = 0; char ch = getchar(); bool f = false;
    while(!isdigit(ch)) f |= (ch == '-'), ch = getchar();
    while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
    return f ? -x : x;
}

int N, G;

struct state
{
    int date, idx, delta, newidx;
    inline bool operator <(const state &rhs) const{
        return date < rhs.date;
    }
}pool[MAXN];

namespace stree
{
    #define mid ((l + r) >> 1)
    #define ls (o << 1)
    #define rs ((o << 1) | 1)

    int node[MAXN << 2];

    inline void pushup(int o){
        node[o] = max(node[ls], node[rs]);
    }

    int modify(int o, int l, int r, int p, int v){
        if(l == r) return node[o] += v, node[o];
        int tmp;
        if(p <= mid) tmp = modify(ls, l, mid, p, v);
        else tmp = modify(rs, mid + 1, r, p, v);
        return pushup(o), tmp;
    }
}

vector<int> cp;
void compress(){
    for(int i = 1; i <= N; i++) cp.push_back(pool[i].idx);
    cp.push_back((1 << 29));
    sort(cp.begin(), cp.end());
    cp.erase(unique(cp.begin(), cp.end()), cp.end());
    for(int i = 1; i <= N; i++){
        pool[i].newidx = upper_bound(cp.begin(), cp.end(), pool[i].idx) - cp.begin();
    }
}

map<int, int> M;
int main()
{
    //freopen("p4087.in", "r", stdin);
    cin>>N>>G;

    int ans = 0;
    for(int i = 1; i <= N; i++){
        int date = read(), idx = read(), delta = read();
        pool[i] = (state){date, idx, delta};
    }
    sort(pool + 1, pool + N + 1);

    compress(); int maxlast = 0;
    M[0] = (1 << 29);
    
    for(int i = 1; i <= N; i++){
        maxlast = stree::node[1];
        int val = stree::modify(1, 1, cp.size(), pool[i].newidx, pool[i].delta);
        
        if(M.find(val) == M.end()) M[val] = 0;
        M[val - pool[i].delta]--, M[val]++;
        
        int maxnow = stree::node[1];
        if(val < maxnow && (val - pool[i].delta) == maxlast) ++ans;
        if(val == maxnow){
            if((val - pool[i].delta) == maxlast && M[val] + M[maxlast] == 1) continue;
            ++ans;
        }
    }
    cout<<ans<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/wsmrxc/p/9439342.html