zoukankan      html  css  js  c++  java
  • P2898 [USACO08JAN]haybale猜测Haybale Guessing

    好题.
    搬运一下luogu的题解, 讲的挺清楚的.

    题意:给出一些区间的最小值 求问 最早哪个问题会产生矛盾 输出
    我们可以二分判断 哪个地方最早出现矛盾
    然后每次针对二分的一个值 我去判断一下是否成立 我首先针对权值排序
    然后从大到小去覆盖 出现第一个无法覆盖的区域我就返回false

    当然, 此处无法覆盖的区域其实有两种情况 :

    1. 多个区间最小值相同却没有一个共同包含的区间;
    2. 多个区间最小值相同且有一个共同包含的区间, 但是这个区间被一个最小值更大的区间包含.

    为了处理这两种不合法的情况, 我们先二分不合法端点所在位置, 然后按照所给的最小值从大到小排序.
    对于情况一, 我们记录下相同权值的区间中左端点的最大值右端点的最小值. 假如左端点的最大值 (>) 右端点的最小值, 就说明这之间没有被这些区间完全覆盖, 显然不合法.
    情况二用线段树或者并查集都可以.
    假如遇见了这两种情况, 就缩小二分的右端点即可.
    这里我用的线段树.

    #include <cstdio>
    #include <cstring>
    #include <cassert>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int MAXN = 1e6 + 10;
    const int MAXQ = 25000 + 10;
    inline int read(){
        char ch = getchar(); int x = 0;
        while(!isdigit(ch)) ch = getchar();
        while(isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();
        return x;
    }
    
    int N, Q;
    struct Query
    {
        int l, r, v;
        bool operator >(const Query &rhs) const {
            return v > rhs.v;
        }
    }que[MAXQ], q[MAXQ];
    
    namespace stree
    {
        #define mid ((l + r) >> 1)
        #define ls (o << 1)
        #define rs ((o << 1) | 1)
    
        struct Node
        {
            int val, tag;
        }node[MAXN << 2];
    
        inline void pushup(int o) {
            node[o].val = node[ls].val + node[rs].val;
        }
    
        inline void givetag(int o, int l, int r, int v) {
            node[o].val = (r - l + 1) * v;
            node[o].tag = v;
        }
    
        inline void pushdown(int o, int l, int r) {
            int &v = node[o].tag;
            if(v == 0) return;
            givetag(ls, l, mid, v), givetag(rs, mid + 1, r, v);
            v = 0;
        } 
    
        void modify(int o, int l, int r, int a, int b, int v) {
            if(l > b || r < a) return ;
            if(a <= l && r <= b) return givetag(o, l, r, v);
            pushdown(o, l, r);
            modify(ls, l, mid, a, b, v), modify(rs, mid + 1, r, a, b, v); 
            return pushup(o);
        }
    
        int query(int o, int l, int r, int a, int b) {
            if(l > b || r < a) return 0;
            if(a <= l && r <= b) return node[o].val;
            pushdown(o, l, r);
            return query(ls, l, mid, a, b) + query(rs, mid + 1, r, a, b);
        }
        #undef mid
        #undef ls
        #undef rs
    }
    
    inline bool check(int x) {
        using namespace stree;
        memcpy(q, que, (x + 1) * sizeof(Query));
        sort(q + 1, q + x + 1, greater<Query>());
        memset(node, 0, ((N + 1) << 2) * sizeof(Node));
        for(int i = 1; i <= x; i++) {
            int lmin = q[i].l, rmin = q[i].r, lmax = q[i].l, rmax = q[i].r;
            while(i + 1 <= x && q[i].v == q[i + 1].v) {
                ++i;
                lmin = min(lmin, q[i].l), rmin = min(rmin, q[i].r);
                lmax = max(lmax, q[i].l), rmax = max(rmax, q[i].r);
            }
            if(lmax > rmin || query(1, 1, N, lmax, rmin) == (rmin - lmax + 1)) return false;
            modify(1, 1, N, lmin, rmax, 1);
        }
        return true;
    }
    
    int main(){
        // freopen("p2898.in", "r", stdin);
        cin>>N>>Q;
        for(int i = 1; i <= Q; i++)
            que[i].l = read(), que[i].r = read(), que[i].v = read();
        int l = 1, r = Q + 1;
        while(l < r) {
            int mid = (l + r) >> 1;
            if(check(mid)) l = mid + 1;
            else r = mid;
        }
        if(r == Q + 1) puts("0");
        else printf("%d
    ", l);
        return 0;
    }
    
  • 相关阅读:
    KMP的next[]数组
    [Gauss]HDOJ3976 Electric resistance
    [Gauss]POJ2065 SETI
    [Gauss]POJ2947 Widget Factory
    更好的 SQL 模式的 10 条规则
    BZOJ2460: [BeiJing2011]元素
    BZOJ2115: [Wc2011] Xor
    洛谷P3164 [CQOI2014]和谐矩阵
    POJ1222熄灯问题
    POJ1830开关问题
  • 原文地址:https://www.cnblogs.com/wsmrxc/p/9811949.html
Copyright © 2011-2022 走看看