Description
有一个长度为 n n 的正整数序列,序列中元素两两不同且都在[1,109][1,109]中。
你不知道这个序列是什么。
现在有 Q Q 个询问l,rl,r,每次询问序列中区间[l,r][l,r]的最小值,有一个人回答了这 Q Q 个问题。
但是他太不靠谱,回答可能会自相矛盾。
于是我们要求出一个最小的 p p ,回答的 p p 个询问后出现了答案自相矛盾的情况。
如果所有的 Q Q 个答案是不互相矛盾的,就输出00。
Input
第一行两个整数。
接下来 Q Q 行,第 i i 行三个整数 li,ri,ansi li,ri,ansi,表示第 i i 个询问[li,ri][li,ri],回答的答案为 ansi ansi。
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≤106,m≤25000,1≤ansi≤109
Solution
考虑二分答案,接下来判断前mid个询问是否矛盾。
把所有询问按照答案从大到小排序,把答案相同的那些询问放在一起,求出区
间交及区间并,如果区间交为空说明序列中有重复数字,直接无解;否则我们看
看区间交是否全被覆盖,如果全被覆盖显然之前的区间答案错误产生矛盾,如
果没全被覆盖我们就把区间并(由于区间交不为空区间并显然是一段连续区间)
进行覆盖。
正确性在于如果有 l1≤l2≤r2≤l1l1≤l2≤r2≤l1,那么显然有 ans2≥ans1ans2≥ans1,而如果答案小
的区间全被覆盖就相当于 ans2<ans1ans2<ans1。这就产生了矛盾。
那么我们可以用线段树或并查集的做法,下面就讲讲并查集。
如果我们将要覆盖[l,r][l,r],那么我们就要使l~r合并到r+1去,所以当fai≠ifai≠i
时就说明该区域已被覆盖,并且当 fai=faj fai=faj 时说明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.

155

被折叠的 条评论
为什么被折叠?



