-
F - Another LIS
HDU - 3564 - 题意:给你N个数的位置。数字i的位置为a[i],每插一个位置,要求输出当前最大的LIS。
- 思路:线段树插空法逆序处理出每一个数字所在的位置,然后按照数组去访问,因为题目输入顺序是 1放在哪个位置
- 2放在那个位置 ..... 所以按照1-n去访问这些数数字即可,由于数字是升序访问的,那么他们的位置只要符合单调升的
- 就是 这些数在序列中为 上升子序列。O(nlogn)处理出每个 数字出现时的 最长LIS即可。
-
#include<bits/stdc++.h> using namespace std; #define maxn 123456 int t,n,a[maxn],id[maxn]; int ls[maxn],ans; struct node { int l,r,wlen; } tree[4*maxn]; void bulid(int root,int l,int r) { tree[root].l=l; tree[root].r=r; tree[root].wlen=r-l+1; if(l==r)return ; int mid=(l+r)>>1; bulid(root*2,l,mid); bulid(root*2+1,mid+1,r); } void updata(int root,int pos,int data) { if(tree[root].l==tree[root].r) { id[data]=tree[root].l; tree[root].wlen=0; return ; } tree[root].wlen--; if(pos<=tree[root*2].wlen)updata(root*2,pos,data); else updata(root*2+1,pos-tree[root*2].wlen,data); } int main() { scanf("%d",&t); for(int q=1; q<=t; q++) { ans=0; scanf("%d",&n); bulid(1,1,n); for(int i=1; i<=n; i++) scanf("%d",&a[i]); for(int i=n; i>=1; i--) updata(1,a[i]+1,i); printf("Case #%d:\n",q); for(int i=1; i<=n; i++) { if(i==1) ls[ans++]=id[i]; else if(id[i]>ls[ans-1]) ls[ans++]=id[i]; else { int pos=lower_bound(ls,ls+ans,id[i])-ls; ls[pos]=id[i]; } printf("%d\n",ans); } puts(""); } return 0; }