[Luogu 3902]Increasing

Description

Input

Output

Sample Input

3
1 3 2

Sample Output

1

HINT

这里要用到一种技巧:

我们认为改出来的数要是整数情况下:

a[i]>a[i-1]等价于a[i]-i>=a[i-1]-i+1

这样求最长不下降子序列就行了

因为当j<i    a[j]-j==a[i]-i时,说明他们中间可以填的数有i-j+1个,需要的正好也是i-j+1

所以这样是肯定可以的

如果不处理就求最长上升子序列,可能会出现中间部分无数可以填入(所以只适用于填实数)

nlogn求最长不下降有很多方法,这里用的是离散+线段树

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int c[400001],sz;
 7 int a[100001],b[100001],n,ans,f[100001];
 8 void pushup(int rt)
 9 {
10   c[rt]=max(c[rt*2],c[rt*2+1]);
11 }
12 void update(int rt,int l,int r,int x,int d)
13 {
14   if (l==r)
15     {
16       c[rt]=d;
17       return;
18     }
19   int mid=(l+r)/2;
20   if (x<=mid) update(rt*2,l,mid,x,d);
21   else update(rt*2+1,mid+1,r,x,d);
22   pushup(rt);
23 }
24 int query(int rt,int l,int r,int L,int R)
25 {
26   if (l>=L&&r<=R)
27     {
28       return c[rt];
29     }
30   int mid=(l+r)/2,s=0;
31   if (L<=mid) s=max(s,query(rt*2,l,mid,L,R));
32   if (R>mid) s=max(s,query(rt*2+1,mid+1,r,L,R));
33   return s;
34 }
35 int main()
36 {int i,num=0;
37   cin>>n;
38   for (i=1;i<=n;i++)
39     {
40       scanf("%d",&a[i]);
41       num++;
42       b[num]=a[i]-i;
43       a[i]-=i;
44     }
45   sort(b+1,b+num+1);
46   sz=unique(b+1,b+num+1)-(b+1);
47   for (i=1;i<=n;i++)
48     a[i]=lower_bound(b+1,b+sz+1,a[i])-b;
49   for (i=1;i<=n;i++)
50     {
51       f[i]=query(1,1,sz,1,a[i])+1;
52       update(1,1,sz,a[i],f[i]);
53       ans=max(ans,f[i]);
54     }
55   cout<<n-ans;
56 }

 

posted @ 2017-10-08 10:09  Z-Y-Y-S  阅读(221)  评论(0编辑  收藏  举报