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 m i n ≥ B m i n A_{min}\geq B_{min} AminBmin,否则也有矛盾。

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

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值