zoukankan      html  css  js  c++  java
  • bzoj 2809

    这道题算事那个apio里面唯一我能做的题了= =

    链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2809

    题目一看完很容易想到一个贪心,然后我们需要维护以某一个节点为根的权值大小关系,如果知道一个子树的大小关系那么子树的根作为管理员的答案就可以求了。然后子树合并= =splay 可搞,大多数说的左偏树(某种堆)也可以,还有很多= =搞搞就好= =我总结一下左偏树:

    1.merge 和smt 一样

    2.维护val 和dis, 保证lson的dis > rson 的dis

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    typedef long long qword;
    const qword maxn = 100100;
    qword n, S, v[maxn], c[maxn]; 
    
    struct node {
        qword val, dis, size, sum;
        node *l, *r;
    }e[maxn], *rt[maxn]; qword ne = 0;
    
    void swap(node* &a, node* &b) {
        node* x = a;
        a = b; b = x;
    }
    
    void update(node* now) {
        now-> size = 1, now-> sum = now-> val;
        if(now-> l) now-> size += now-> l-> size, now-> sum += now-> l-> sum;
        if(now-> r) now-> size += now-> r-> size, now-> sum += now-> r-> sum;
    }
    
    node* merge(node* a, node* b) {
        if(!a) return b;
        if(!b) return a;
        if(a-> val < b-> val) swap(a, b);
        a-> r = merge(a-> r, b);
        qword dl = a-> l ? a-> l-> dis : -1;
        qword dr = a-> r ? a-> r-> dis : -1;
        if(dl < dr) swap(a-> l, a-> r);
        a-> dis = a-> r ? a-> r-> dis + 1 : 0;
        update(a);
        return a;
    }
    
    void pop(node* &a) {
        a = merge(a-> l, a-> r);
    }
    
    qword top(node* a) {
        return a ? a-> val : -1;
    }
    
    struct edge {
        qword t; edge* next;
    }se[maxn * 2], *head[maxn]; qword oe = 0;
    
    void addedge(qword f, qword t) {
        se[oe].t = t, se[oe].next = head[f], head[f] = se + oe ++;
    }
    
    void read() {
        scanf("%lld%lld", &n, &S);
        for(qword i = 1; i <= n; ++ i) {
            qword u; scanf("%lld%lld%lld", &u, &v[i], &c[i]);
            if(u) addedge(u, i), addedge(i, u);
        }
    }
    
    qword ans = 0;
    
    void sov() {
        for(qword i = n; i >= 1; -- i) {
            rt[i] = e + ne ++;
            rt[i]-> val = v[i], rt[i]-> size = 1, rt[i]-> sum = rt[i]-> val;
            rt[i]-> l = rt[i]-> r = NULL;
            for(edge* p = head[i]; p; p = p-> next) {
                if(p-> t > i) {
                    rt[i] = merge(rt[i], rt[p-> t]);
                }
            }
            while(rt[i] && rt[i]-> sum > S) pop(rt[i]);
            if(rt[i]) ans = max(ans, rt[i]-> size * c[i]);
        }
        printf("%lld
    ", ans);
    }
    
    int main() {
        //freopen("test.in", "r", stdin);
        //freopen("test.out", "w", stdout);
        read(), sov();
        return 0;
    }
  • 相关阅读:
    几种存储器类型总结
    几种存储器类型总结
    JPEG2000开发SDK及其特点
    JPEG2000开发SDK及其特点
    测试代码的编写
    测试代码的编写
    关于opencv的几个小总结
    关于opencv的几个小总结
    假设检验与判决准则(一)
    Canny算法源码,欢迎交流
  • 原文地址:https://www.cnblogs.com/ianaesthetic/p/4139186.html
Copyright © 2011-2022 走看看