1. 程式人生 > >poj 3657Haybale Guessing(並查集 加染色)

poj 3657Haybale Guessing(並查集 加染色)

Description

The cows, who always have an inferiority complex about their intelligence, have a new guessing game to sharpen their brains.

A designated 'Hay Cow' hides behind the barn and creates N (1 ≤ N ≤ 1,000,000) uniquely-sized stacks (conveniently numbered 1..N) of hay bales, each with 1..1,000,000,000 bales of hay.

The other cows then ask the Hay Cow a series of Q (1 ≤ Q ≤ 25,000) questions about the the stacks, all having the same form:

What is the smallest number of bales of any stack in the range of stack numbers Ql..Qh (1 ≤ Ql ≤ NQl ≤ Qh ≤ N)?

The Hay Cow answers each of these queries with a single integer A

 whose truthfulness is not guaranteed.

Help the other cows determine if the answers given by the Hay Cow are self-consistent or if certain answers contradict others.

Input

* Line 1: Two space-separated integers: N and Q
* Lines 2..Q+1: Each line contains three space-separated integers that represent a single query and its reply: Q

l, Qh, and A

Output

* Line 1: Print the single integer 0 if there are no inconsistencies among the replies (i.e., if there exists a valid realization of the hay stacks that agrees with all Q queries). Otherwise, print the index from 1..Q of the earliest query whose answer is inconsistent with the answers to the queries before it.

Sample Input

20 4
1 10 7
5 19 7
3 12 8
11 15 12

Sample Output

3

Source

並查集加染色

數軸上有n個點,沒個點上的值都不同。然後給你Q次詢問和答案,輸入l,r,x,表示在區間[l,r]最小值為x,然後問你最早在哪個地方出現矛盾。 區間染色問題,可以用並查集來做。先二分出現矛盾的地方p,然後將1~p的詢問值按大到小排序,若對於最小值相同的區間中出現不相交的兩個區間,那麼矛盾出現。 那麼合法的情況就是這些最小值相同的區間必然是兩兩相交的,那麼記錄最小的左端點L和最大的右端點R,然後將[L,R]與L-1合併。所以在判斷的時候還有判一下 當前最小值相同的區間的交集是否之前出現過,若出現過,則矛盾。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define maxn 1000005
struct node
{
    int l,r,num;
};
int n,q;
int father[maxn];
node a[maxn];
node tmp[maxn];
int find(int x)
{
    while(father[x]!=x)
    x=father[x];
    return x;
}
int cmp(node a,node b)
{
    return a.num>b.num;
}
bool check(int tot)
{
    for(int i=1;i<=n;i++)
    father[i]=i;
    for(int i=1;i<=tot;i++)
    tmp[i]=a[i];
    sort(tmp+1,tmp+1+tot,cmp);
    for(int i=1,j;i<=tot;i=j+1)
    {
        j=i;
        int l=tmp[i].l;
        int r=tmp[i].r;
        int L=tmp[i].l;
        int R=tmp[i].r;
        while(j<tot&&tmp[j].num==tmp[j+1].num)
        {
            j++;
            l=max(l,tmp[j].l);
            r=min(r,tmp[j].r);
            L=min(L,tmp[j].l);
            R=max(R,tmp[j].r);
        }
        if(l>r||l>find(r))
        return 0;
        while(L<=R)
        {
            if(find(R)==R)
            {
                father[R]=find(L-1);
                R--;

            }
            else R=father[R];
        }
    }
return 1;
}
int main()
{
    while(~scanf("%d%d",&n,&q))
    {
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].num);

        }
        int l=1;
        int r=q;
        int ans=0;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(check(mid))
            l=mid+1;
            else
            {
                ans=mid;
                r=mid-1;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}