Description
有一个长度为
n
n
的正整数序列,序列中元素两两不同且都在
[1,109]
[
1
,
10
9
]
中。
你不知道这个序列是什么。
现在有
Q
Q
个询问
l,r
l
,
r
,每次询问序列中区间
[l,r]
[
l
,
r
]
的最小值,有一个人回答了这
Q
Q
个问题。
但是他太不靠谱,回答可能会自相矛盾。
于是我们要求出一个最小的
p
p
,回答的
p
p
个询问后出现了答案自相矛盾的情况。
如果所有的
Q
Q
个答案是不互相矛盾的,就输出
0
0
。
Input
第一行两个整数。
接下来
Q
Q
行,第
i
i
行三个整数
li,ri,ansi
l
i
,
r
i
,
a
n
s
i
,表示第
i
i
个询问
[li,ri]
[
l
i
,
r
i
]
,回答的答案为
ansi
a
n
s
i
。
output
按照题目要求输出一行一个整数。
Sample Input
20 4
1 10 7
5 19 7
3 12 8
11 15 12
Sample Output
3
Data Constraint
n≤106,m≤25000,1≤ansi≤109 n ≤ 10 6 , m ≤ 25000 , 1 ≤ a n s i ≤ 10 9
Solution
考虑二分答案,接下来判断前mid个询问是否矛盾。
把所有询问按照答案从大到小排序,把答案相同的那些询问放在一起,求出区
间交及区间并,如果区间交为空说明序列中有重复数字,直接无解;否则我们看
看区间交是否全被覆盖,如果全被覆盖显然之前的区间答案错误产生矛盾,如
果没全被覆盖我们就把区间并(由于区间交不为空区间并显然是一段连续区间)
进行覆盖。
正确性在于如果有
l1≤l2≤r2≤l1
l
1
≤
l
2
≤
r
2
≤
l
1
,那么显然有
ans2≥ans1
a
n
s
2
≥
a
n
s
1
,而如果答案小
的区间全被覆盖就相当于
ans2<ans1
a
n
s
2
<
a
n
s
1
。这就产生了矛盾。
那么我们可以用线段树或并查集的做法,下面就讲讲并查集。
如果我们将要覆盖
[l,r]
[
l
,
r
]
,那么我们就要使l~r合并到r+1去,所以当
fai≠i
f
a
i
≠
i
时就说明该区域已被覆盖,并且当
fai=faj
f
a
i
=
f
a
j
时说明i,j被同一区域覆盖。易得最多只合并
n
n
次。
Code
var l,r,mid,fax,fay,i,n,t:longint;
g,f:array[1..2] of longint;
a,b:array[0..30000,1..3] of longint;
fa:array[1..1000005] of longint;
function get(x:longint):longint;
begin
if fa[x]=x then exit(x);
fa[x]:=get(fa[x]);exit(fa[x]);
end;
procedure qsort(x,y:longint);
var i,j:longint;
k:int64;
begin
i:=x;
j:=y;
k:=b[(i+j) div 2,3];
repeat
while b[i,3]>k do inc(i);
while b[j,3]<k do dec(j);
if i<=j then begin
b[0]:=b[i];
b[i]:=b[j];
b[j]:=b[0];
inc(i);dec(j);
end;
until i>j;
if i<y then qsort(i,y);
if j>x then qsort(x,j);
end;
function min(x,y:longint):longint;
begin if x<y then exit(x);exit(y);end;
function max(x,y:longint):longint;
begin if x>y then exit(x);exit(y);end;
function pan(x:longint):boolean;
begin
for i:=1 to x do b[i]:=a[i];
for i:=1 to n+1 do fa[i]:=i;
qsort(1,x);
f[1]:=b[1,1];f[2]:=b[1,2];
g[1]:=b[1,1];g[2]:=b[1,2];
b[x+1,3]:=-1;
for i:=2 to x+1 do begin
if b[i,3]=b[i-1,3] then begin
if (b[i,1]>f[2]) or (b[i,2]<f[1]) then exit(false) else
f[1]:=max(f[1],b[i,1]);
f[2]:=min(f[2],b[i,2]);
g[1]:=min(g[1],b[i,1]);
g[2]:=max(g[2],b[i,2]);
continue;
end else begin
fax:=get(f[1]);
fay:=get(f[2]+1);
if fax=fay then exit(false);
fax:=get(g[1]);
fay:=get(g[2]+1);
while fax<>fay do begin
fa[fax]:=fax+1;
fax:=get(fax+1);
end;
f[1]:=b[i,1];f[2]:=b[i,2];
g[1]:=b[i,1];g[2]:=b[i,2];
end;
end;
exit(true);
end;
begin
assign(input,'bales.in');reset(input);
assign(output,'bales.out');rewrite(output);
readln(n,t);
for i:=1 to t do
readln(a[i,1],a[i,2],a[i,3]);
l:=1;r:=t;
while l<r do begin
mid:=(l+r) div 2;
if pan(mid) then l:=mid+1 else r:=mid;
end;
if (l=t) and (pan(l)) then writeln(0) else writeln(l);
close(input);
close(output);
end.