bzoj 1109 [POI2007]堆积木Klo(LIS)
【题意】
n个数的序列,删除一个数后序列左移,求最后满足i==a[i]的最大个数。
【思路】
设最终得到a[i]==i的序列为s,则s应满足:
i<j,a[i]<a[j],i-a[i]<=j-a[j]
最后一项代表后边的移动距离不少于前边的。
因为i=i-a[i]+a[i]
所以只要满足i-a[i]单调不减,a[i]单调递增则i一定递增。
则问题转化为一个二维偏序问题,O(nlogn)求LIS。用个BIT即可。
【代码】
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long ll; 8 const int N = 2e5+10; 9 10 struct Node { 11 int a,b; 12 bool operator <(const Node& rhs) const { 13 if(a!=rhs.a) return a<rhs.a; 14 else return b<rhs.b; 15 } 16 }ns[N]; 17 18 int C[N],mx; 19 void upd(int x,int v) { 20 for(;x<=mx;x+=x&-x) 21 C[x]=max(C[x],v); 22 } 23 int query(int x) { 24 int res=0; 25 for(;x;x-=x&-x) 26 res=max(res,C[x]); 27 return res; 28 } 29 30 ll read() { 31 char c=getchar(); ll f=1,x=0; 32 while(!isdigit(c)) { 33 if(c=='-') f=-1; 34 c=getchar(); 35 } 36 while(isdigit(c)) 37 x=x*10+c-'0', 38 c=getchar(); 39 return x*f; 40 } 41 42 int n,a[N]; 43 44 int main() 45 { 46 //freopen("klo.in","r",stdin); 47 //freopen("klo.out","w",stdout); 48 n=read(); 49 int tot=0; 50 for(int i=1;i<=n;i++) { 51 a[i]=read(); 52 mx=max(mx,a[i]); 53 if(i>=a[i]) 54 ns[++tot].a=i-a[i],ns[tot].b=a[i]; 55 } 56 sort(ns+1,ns+tot+1); 57 int ans=0; 58 for(int i=1;i<=tot;i++) { 59 int x=query(ns[i].b-1)+1; 60 ans=max(ans,x); 61 upd(ns[i].b,x); 62 } 63 printf("%d\n",ans); 64 return 0; 65 }
P.S.感觉挺巧妙的 %%%
posted on 2016-03-19 19:12 hahalidaxin 阅读(331) 评论(0) 编辑 收藏 举报