zoukankan      html  css  js  c++  java
  • P4053 [JSOI2007]建筑抢修

    贪心+左偏树

    贪心思路:先修快炸的楼

    所以我们可以按照 $T2$ 从大到小做一遍排序,然后从 $1cdots n$ 一个一个去修,如果这栋楼不能修(也就是当前时间已经超过 $T2_{i}$),那我们就不选之前已经修的楼中的一个耗时最长的楼,从而给之后的楼留出时间。如果不选那栋耗时最长的楼,这栋也不能修的话,我们就跳过这栋楼(之前耗时最长的楼留着),去修下一栋楼。

    如何快速查找之前耗时最长的楼?

    这里用的是左偏树,堆和优先队列也可以,对于其他的数据结构,太菜不会。

    代码

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    
    #define RI register int
    const int N = 170001;
    
    using namespace std;
    
    template <class T>
    inline void read(T &x) {
        x = 0; T f = 1; char c = getchar();
        while(c > '9' || c < '0') {
            if(c == '-')
                f = -f;
            c = getchar();
        }
        while(c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = getchar();
        }
        x *= f;
    }
    
    int ls[N], rs[N], dis[N], val[N], root;
    int n;
    struct node {
        int t1, t2;
    }a[N];
    int rt[N];
    
    inline int get(int x) {
        return x == rt[x] ? x : rt[x] = get(rt[x]);
    }
    
    inline int merge(int x, int y) {
        if(!x || !y)
            return x | y;
        if(val[x] < val[y])
            swap(x, y);
        rs[x] = merge(rs[x], y);
        rt[rs[x]] = x;
        if(dis[ls[x]] < dis[rs[x]])
            swap(ls[x], rs[x]);
        dis[x] = dis[rs[x]] + 1;
        return x;
    }
    
    inline int del(int x) {
        int l = ls[x], r = rs[x];
        rt[l] = l, rt[r] = r;
        ls[x] = rs[x] = dis[x] = 0;
        val[x] = -1;
        return merge(l, r);
    }
    
    inline bool cmp(node a, node b) {
        return a.t2 < b.t2;
    }
    
    int sum, ans;
    
    int main() {
        read(n);
        root = n + 1;
        val[root] = -1;
        for(RI i = 1; i <= n; i++)
            read(a[i].t1), read(a[i].t2);
        sort(a + 1, a + 1 + n, cmp);
        for(RI i = 1; i <= n; i++) {
            sum += a[i].t1;
            ans++;
            val[i] = a[i].t1;
            root = merge(root, i);
            if(a[i].t2 < sum)
                sum -= val[root], ans--, root = del(root);
        }
    
        printf("%d
    ", ans);
    
        return 0;
    }
    
  • 相关阅读:
    linux下安装EJBCA 搭建私有CA服务器
    PHP 设计模式之观察者模式
    PHP 设计模式之三种工厂模式
    PHP 设计模式之单例模式
    解決 VMware Workstation 与 Device/Credential Guard 不相容,无法启动虚拟机的问题
    Mac 外接鼠标不好用?这个软件解决你的痛点
    PHP Trait 解决 PHP 单继承问题
    Wordpress 添加图片点击放大效果
    PHP 实现 WebSocket 协议
    Web 网页直接打开 Windows 软件
  • 原文地址:https://www.cnblogs.com/ASTiKi/p/12254058.html
Copyright © 2011-2022 走看看