询问

来源:互联网 发布:sql性能优化 编辑:程序博客网 时间:2024/04/28 22:08

Description

有一个长度为 n 的正整数序列,序列中元素两两不同且都在[1109]中。
你不知道这个序列是什么。
现在有 Q 个询问lr,每次询问序列中区间[l,r]的最小值,有一个人回答了这 Q 个问题。
但是他太不靠谱,回答可能会自相矛盾。
于是我们要求出一个最小的 p ,回答的 p 个询问后出现了答案自相矛盾的情况。
如果所有的 Q 个答案是不互相矛盾的,就输出0

Input

第一行两个整数 nQ
接下来 Q 行,第 i 行三个整数 liriansi,表示第 i 个询问[liri],回答的答案为 ansi

output

按照题目要求输出一行一个整数。

Sample Input

20 4
1 10 7
5 19 7
3 12 8
11 15 12

Sample Output

3

Data Constraint

 n106,m25000,1ansi109

Solution

考虑二分答案,接下来判断前mid个询问是否矛盾。
把所有询问按照答案从大到小排序,把答案相同的那些询问放在一起,求出区
间交及区间并,如果区间交为空说明序列中有重复数字,直接无解;否则我们看
看区间交是否全被覆盖,如果全被覆盖显然之前的区间答案错误产生矛盾,如
果没全被覆盖我们就把区间并(由于区间交不为空区间并显然是一段连续区间)
进行覆盖。
正确性在于如果有 l1l2r2l1,那么显然有 ans2ans1,而如果答案小
的区间全被覆盖就相当于 ans2<ans1。这就产生了矛盾。
那么我们可以用线段树或并查集的做法,下面就讲讲并查集。
如果我们将要覆盖[lr],那么我们就要使l~r合并到r+1去,所以当faii
时就说明该区域已被覆盖,并且当 fai=faj 时说明i,j被同一区域覆盖。易得最多只合并 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;beginassign(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.
1 0