noip模拟题《序》sort

【问题背景】
      zhx 给他的妹子们排序。
【问题描述】
      zhx有N个妹子,他对第i个妹子的好感度为ai, 且所有ai两两不相等。现在N个妹子随意站成一 排,他要将她们根据好感度从小到大排序。 他使用的是冒泡排序算法。如果排序过程中 好感度为ai的妹子和好感度为aj的妹子发生了交换, 那么她们之间会发生一场口角。
      现在 zhx 想知道, 给定妹子的初始排列, 在排序完成后, 最多存在多少个妹子, 她们任意两 人之间没发生过口角。
      正式地, 考虑对数组ai进行冒泡排序, 如果ai和aj在排序过程中发生交换,那么在两个元素之 间连一条边。你需要求出,排序结束后,最多存在多少个元素,其中任意两个元素之间不存在连边。
【输入格式】
      第一行两个整数 N, 表示妹子数量。
      接下来一行 N 个整数ai,表示初始第 i 个妹子的好感度。
【输出格式】
      一行一个整数, 表示最多满足要求的妹子的个数。
【样例输入】
3
3 1 2
【样例输出】
2
【样例解释】
{1, 2}。
【数据规模与约定】
      对于30%的数据, 1 ≤n≤ 16。
      对于70%的数据, 1 ≤n≤ 5000。
      对于100%的数据, 1 ≤n≤ 100000, 0 ≤ai<n。

 

     (当时看到实在不会做啊,还是QTY_YTQ神说这就是求最长上升子序列长度,好劲啊)
      就是i和j两个妹子不交换,当且仅当ai<aj,所以只要求最长上升子序列长度就行了。
     (然而当时我只会n2算法70分,QTY_YTQ神写了个线段树维护A了,%%%)

      正解是nlogn的最长上升子序列:

 1 program sort(input,output);
 2 const
 3   inf=123456789;
 4 var
 5   a,f,c:array[0..100010]of longint;
 6   i,k,n:longint;
 7 function min(a,b:longint):longint;
 8 begin
 9    if a<b then exit(a) else exit(b);
10 end;
11 function find(x:longint):longint;
12 var
13   l,r,mid:longint;
14 begin
15    if x<c[1] then exit(0);
16    l:=1;r:=k;
17    while l<r-1 do
18       begin
19          mid:=(l+r)>>1;
20          if c[mid]>x then r:=mid-1 else l:=mid;
21       end;
22    if c[r]<x then exit(r) else exit(l);
23 end;
24 begin
25    assign(input,'sort.in');assign(output,'sort.out');reset(input);rewrite(output);
26    readln(n);
27    for i:=1 to n do read(a[i]);
28    for i:=1 to n do c[i]:=inf;
29    k:=0;
30    for i:=1 to n do begin f[i]:=find(a[i])+1;if c[f[i]]=inf then inc(k);c[f[i]]:=min(c[f[i]],a[i]); end;
31    write(k);
32    close(input);close(output);
33 end.

 

posted @ 2017-02-06 09:37  Klaier  阅读(239)  评论(0编辑  收藏  举报