[bzoj1109]堆积木

用f[i]表示前i个数,i必须被贡献的答案,考虑转移,枚举下一个被贡献的数j,那么j需要满足:1.$j<i$;2.$a[j]<a[i]$;3.$a[i]-(i-j+1)\le a[j]$,化简后即$j-a[j]\le i-a[i]$;4.$a[i]\le i$
这是一个三维偏序,但发现第二个限制和第三个限制可以凑出第一个限制,即第一个限制和忽略,按照某一维排序,对另一维求lis即可(注意当$a[i]=a[j]$时要让i-a[i]逆序排序,来保证$a[j]<a[i]$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,x,y,a[100005],b[100005],id[100005];
 4 bool cmp(int x,int y){
 5     return (a[x]<a[y])||(a[x]==a[y])&&(x-a[x]>y-a[y]);
 6 }
 7 int main(){
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;i++){
10         scanf("%d",&a[i]);
11         id[i]=i;
12     }
13     sort(id+1,id+n+1,cmp);
14     for(int i=1;i<=n;i++)
15         if (a[id[i]]<=id[i]){
16             x=upper_bound(b+1,b+b[0]+1,id[i]-a[id[i]])-b;
17             b[0]=max(b[0],x);
18             b[x]=id[i]-a[id[i]];
19         }
20     printf("%d",b[0]);
21 }
View Code

猜你喜欢

转载自www.cnblogs.com/PYWBKTDA/p/12075755.html