• HDU 5280 Lights


    题目传送门
    https://www.bilibili.com/video/BV1Tk4y1m7VM?p=23
    没看懂,等功力够了,再来填坑吧

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <ctime>
    #include <cmath>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <climits>
    #include <queue>
    #include <map>
    #include <set>
    #include <sstream>
    #include <cassert>
    
    using namespace std;
    typedef pair<int, int> PII;
    #define x first
    #define y second
    
    const int N = 5e5 + 100;
    const int M = 50000;
    
    int prex[M], prey[M], n;
    
    PII p[N];
    /*主席树*/
    struct Node {
        int l, r;
        int ls, rs;
        int sum;
    } tr[N * 32];
    
    int root[N], idx;
    
    void insert(int &p, int l, int r, int x) {
        int q = idx++;
        tr[q] = tr[p];
        p = idx - 1;
        tr[p].sum++;
        if (l == r) return;
        int mid = (l + r) >> 1;
        if (x <= mid)
            insert(tr[p].l, l, mid, x);
        else
            insert(tr[p].r, mid + 1, r, x);
    }
    
    //左根,右根,当前区间,目标区间
    int query(int i, int j, int l, int r, int L, int R) {
        if (r < L || l > R) return 0;                       //不在范围内,返回0
        if (l >= L && r <= R) return tr[j].sum - tr[i].sum; //计算前缀和的差
        int mid = (l + r) >> 1;
        return query(tr[i].l, tr[j].l, l, mid, L, R) + query(tr[i].r, tr[j].r, mid + 1, r, L, R);
    }
    
    /*主席树*/
    bool solve() {
        memset(prex, 0, sizeof(prex));
        memset(prey, 0, sizeof(prey));
        memset(root, 0, sizeof root);
    
        //构建主席树的0号
        root[0] = 0;
        tr[0].l = tr[0].r = tr[0].sum = tr[0].ls = tr[0].rs = 0;
        idx = 1;
    
        int last = 0;
        for (int i = 1; i <= n; i++) {
            //如果相邻的结点坐标一样,不处理
            if (p[i].x == p[i - 1].x && p[i].y == p[i - 1].y) continue;
            //取出当前点坐标
            int x = p[i].x, y = p[i].y;
    
            int xx = p[prey[y]].x, yy = p[prex[x]].y;
            root[x] = root[last];
    
            insert(root[x], 1, M, y);
    
            if (query(root[xx], root[x], 1, M, yy + 1, y - 1)) return false;
            last = x, prex[x] = i, prey[y] = i;
        }
        return true;
    }
    
    int main() {
        //本题使用cin直接TLE,即使采用sync进行cin优化,依然也有时超时,只能采用scanf来读取
        while (~scanf("%d", &n) && n) {
            //每个路灯的坐标(x,y)
            for (int i = 1; i <= n; i++) scanf("%d%d", &p[i].x, &p[i].y);
    
            //主席树,一般都是要求排序的,这里是用x坐标为基准进行排序的
            sort(p + 1, p + 1 + n);
            bool flag = solve();
    
            //一正一反两次
            for (int i = 1; i <= n; i++) p[i].x = M - p[i].x;
            sort(p + 1, p + 1 + n);
            flag &= solve();
    
            if (flag)
                puts("YES");
            else
                puts("NO");
        }
        return 0;
    }
    
  • 相关阅读:
    封神台靶机练习第一章:SQL注入攻击原理
    java基础复习-自定义注解1(如何自定义注解?)
    java复习预科知识-Markdown学习
    leetcode-888-公平的糖果交换
    leetcode-884-两句话中的不常见单词
    leetcode-139-单词拆分(递归超时,动归解决)
    leetcode-134-加油站
    leetcode-91-解码方法(动态规划和递归两种解法)
    leetcode-56-合并区间
    leetcode-55-跳跃游戏
  • 原文地址:https://www.cnblogs.com/littlehb/p/16220832.html
Copyright © 2020-2023  润新知