POJ

来源:互联网 发布:歌词中的励志句子知乎 编辑:程序博客网 时间:2024/05/21 10:06

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
原创粉丝点击