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 ≤ N; Ql ≤ Qh ≤ N)?
The Hay Cow answers each of these queries with a single integer A
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
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;
}