Haybale Guessing 区间并查集

Haybale 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 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: Ql, 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

题意:有一个没有重复数字的序列,给定多个条件:区间[x,y]的最小值,输出最早出现矛盾的条件编号。
这题用线段树也能做,不过代码太长了。
由于是没有重复的数字,所以判断是否有矛盾:

  1. 两个区间最小值相同,则一定有交集,否则就有矛盾。
  2. 两个区间A,B最小值不相同,如果A是B的子集,那么(A_{min}geq B_{min}),否则也有矛盾。

这样,可以通过二分求得答案。
注意,排序之后,两个区间最小值相同,则区间并集最小值都相同,用来覆盖,区间交集用来查询是否符合之前的条件。

#include<bits/stdc++.h>
using namespace std;
#define Init(arr,val) memset(arr,val,sizeof(arr))
const int inf=0x3f3f3f3f,mod=1e9+7,MAXN=1e6+8;
typedef long long ll;
struct Node {
    int x,y,val;
    bool operator<(const Node&o)const {
        return val>o.val;
    }
} d[25005],t[25005];
int n,q;
int fa[MAXN];
inline int find(int x) {
    while(x!=fa[x])
        x=fa[x]=fa[fa[x]];
    return x;
}
bool check(int mid) {
    for(int i=0; i<=n+1; ++i)fa[i]=i;
    for(int i=0;i<mid;++i)t[i]=d[i];
    sort(t,t+mid);
    int lmin,lmax,rmin,rmax;
    lmin=lmax=t[0].x;
    rmin=rmax=t[0].y;
    for(int i=1; i<mid; ++i) {
        if(t[i].val==t[i-1].val) {
        //两个区间最小值一样,判断是否有交集
        //可能有3个以上的区间满足,所以要用四个变量记录。
            lmin=min(lmin,t[i].x);
            lmax=max(lmax,t[i].x);
            rmin=min(rmin,t[i].y);
            rmax=max(rmax,t[i].y);
            if(lmax>rmin)return 1;//区间不相交。
        } else {
            if(find(lmax)>rmin)return 1;//
            for(int j=lmin; j<=rmax; ++j) {
                j=find(j);
                fa[j]=find(rmax+1);//不+1的话还要多个判断是否区间只有一个点。
            }
            lmin=lmax=t[i].x;
            rmin=rmax=t[i].y;
        }
    }
    if(find(lmax)>rmin)return 1;//可能没有更新
    return 0;
}
int main() {
    std::ios::sync_with_stdio(0);
    std::cin.tie(0);
    cin>>n>>q;
    for(int i=0; i<q; ++i)
        cin>>d[i].x>>d[i].y>>d[i].val;
    int l=1,r=q,ans=0;
    while(l<=r) {
        int mid=(r+l)>>1;
        if(check(mid)) {
            r=mid-1;
            ans=mid;
        } else l=mid+1;
    }
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/foursmonth/p/14145148.html