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]的最小值,输出最早出现矛盾的条件编号。
这题用线段树也能做,不过代码太长了。
由于是没有重复的数字,所以判断是否有矛盾:
- 两个区间最小值相同,则一定有交集,否则就有矛盾。
- 两个区间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;
}