POJ - 3657

Haybale Guessing

【Point】

conveniently numbered 1..N

看题的时候没能注意到这句话,思路一直被困在更新区间,比较区间上面,但是这次的区间更新并不能取代现有的区间,也就是区间的个数只会不断增加而不可能减少,因此每次需要对比的区间也就不断增加,这显然是不可能在较快时间内完成的。

我对这道题目的思考也就此打住,后来在翻看题解之后才发现这句话,但此时业已怠惰,就着题解写完了。

【Algorithm】

因为每一个值的大小都是不一样的,所以所有最小值相同的区间必然存在交集,如果不存在交集,是不可能造成同样的最小值的,也就是说,最小值的安放位置至关重要。

事实上,我们也正是从这一点进行破题的,由安放最小值的位置来考虑会有两种情况下出现冲突。
情况1:同一最小值区间没有交集,这种情况我们已经论述过,不再赘述。
情况2:在某一区间内,不仅拥有问答出来的最小值,还有比问答更小的值,这明显是矛盾的。

从安放最小值的理论出发,我们可知道冲突与不冲突仅仅和最小值有关,而和其他值无关,我们只需要注意最小值就可以了。并且对于min-1来说min也是无关的,这就是说小的对大的有冲突而大的对小的是没有冲突的。

因此,我们就可以首先安放较大的,再安放较小的,并且较小的是不能存在大的区间里面的。

总结起来就是,【判断交集,染色并集】

【Code】

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

const int maxn = 1e6 + 10;
const int maxq = 25000 + 10;
int n, q;
int num[maxn];

struct Node
{
    int l, r, v;
    Node(int l = 0, int r = 0, int v = 0) : l(l), r(r), v(v){}

    bool operator < (const Node & rhs)
    {
        return v > rhs.v;
    }
    bool examine()
    {
        if (l > r)
            return false;
        for (int i = l; i <= r; i++)
            if (!num[i]) return true;
        return false;
    }
}node[maxq];
vector<Node> pool;

bool check(int u)
{
    vector<Node> pool2(pool.begin(), pool.begin() + u);
    sort(pool2.begin(), pool2.end());
    Node inter, unio;
    inter = unio = pool2[0];
    pool2.push_back(Node(0, 0, 1e9 + 1));
    for (int i = 1; i < pool2.size(); i++)
    {
        Node & use = pool2[i];
        if (use.v == inter.v)
        {
            inter.l = max(inter.l, use.l);
            inter.r = min(inter.r, use.r);
            unio.l = min(unio.l, use.l);
            unio.r = max(unio.r, use.r);
        }
        else
        {
            if (inter.examine())
            {
                for (int i = unio.l; i <= unio.r; i++)
                    num[i] = 1;
            }
            else
                return true;
            inter = unio = use;
        }
    }
    return false;
}

int main()
{
    while (~scanf("%d%d", &n, &q))
    {
        pool.clear();
        int ll, rr, vv;
        for (int i = 0; i < q; i++)
        {
            scanf("%d%d%d", &ll, &rr, &vv);
            node[i] = Node(ll, rr, vv);
            pool.push_back(node[i]);
        }
        int l = 0, r = q;
        int ans = 0;
        while (l <= r)
        {
            memset(num, 0, sizeof(num));
            int mid = l + (r - l) / 2;
            if (check(mid))
            {
                ans = mid;
                r = mid - 1;
            }
            else
                l = mid + 1;
        }
        printf("%d\n", ans);
    }

    return 0;
}

【Note】

这种二分答案法,堪比流氓,本身以为没有记忆化处理,这样的暴力解决会超时,但是没有

Thanks For Watching

–END–

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值