HaybaleGuessing
Time Limit: 1000MS | Memory Limit: 65536K |
Total Submissions: 2626 | Accepted: 706 |
Description
The cows, who always have an inferiority complex about theirintelligence, 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,000bales of hay.
The other cows then ask the Hay Cow a series of Q (1 ≤ Q ≤ 25,000) questions about the thestacks, all having the same form:
What is the smallest number of bales of any stack in the range ofstack 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 Coware 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 thatrepresent a single query and its reply: Ql, Qh, and A
Output
* Line 1: Print the single integer 0 if there are noinconsistencies among the replies (i.e., if there exists a valid realization ofthe hay stacks that agrees with all Q queries). Otherwise, print the index from1..Q of the earliest query whose answer is inconsistent with the answers to thequeries before it.
SampleInput
SampleOutput
Source
USACO 2008 January Gold
算法分析:
题意:给一段长度为n,每个位置上的数都不同的序列a[1..n]和q和问答,每个问答是(x, y, r)代表RMQ(a, x, y) = r, 要你给出最早的有矛盾的那个问答的编号。
①之前已更新这个区间最小值为x,又要更新此区间的子区间(或这个区间)的最小值为更小的数。
②两段区间的最小值相同,但没有交集。(因为题目中说数字互不相同,所以不可能一个数字同时出现在两个位置)
因为要求最小的序号,所以用到二分枚举1到m,
具体操作代码见
代码实现:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1001000;
struct node
{
int x,y,minn;
}a[N],b[N];
int fa[N],ans;
int n,m;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
for(;!isdigit(ch);ch=getchar())if(ch == '-') f = -1;
for(;isdigit(ch);ch=getchar())x = (x << 1) + (x << 3) + ch - '0';
return x * f;
}
int find(int x)
{
return fa[x]==x?x:fa[x]=find(fa[x]);
}
bool cmp(node x,node y)
{
return x.minn>y.minn;
}
bool check(int pos)
{
for(int i=1;i<=n+1;i++)//这里要n+1,不然会超时
fa[i]=i;
for(int i=1;i<=pos;i++)
b[i]=a[i];
sort(b+1,b+pos+1,cmp);
int lmin,lmax,rmin,rmax;
lmin=lmax=b[1].x;
rmax=rmin=b[1].y;
for(int i=2;i<=pos;i++)
{
if(b[i].minn<b[i-1].minn)
{
if(find(lmax)>rmin)//满足情况一
return true;
for(int j=lmin;j<=rmax;j++)//合并上一个区间
{
j=find(j);
fa[j]=find(rmax+1);//全部合并到rmax+1,不然会矛盾
/*如果合并到r,已知[1,2] Min=2,[3,4]Min=4,现在要合并一段区间[1,4] Min = 1,
很明显是矛盾的,但是如果把fa合并到r+1不会判出矛盾。*/
}
lmax=lmin=b[i].x;//更新区间
rmax=rmin=b[i].y;
}
else if(b[i].minn==b[i-1].minn)//情况二
{
lmax=max(lmax,b[i].x);//取交集和并集
lmin=min(lmin,b[i].x);
rmax=max(rmax,b[i].y);
rmin=min(rmin,b[i].y);
if(lmax>rmin)
return true;
}
}
if(find(lmax)>rmin)
return true;
return false;
}
int main()
{
n=read();
m=read();
for(int i=1;i<=m;i++)
a[i].x=read(),
a[i].y=read(),
a[i].minn=read();
int l=1,r=m,mid;
ans=0;
while(r-l>1)
{
int mid =(l+r)>> 1;
if(check(mid))
{ans=mid;
r=mid;
}
else
l=mid;
}
cout<<ans<<endl;
return 0;
}