uva1471 Defense Lines
2016-05-07 20:23
337 查看
题意:给一个长度为n(n<=200000)的序列,删掉某一个连续的序列,使得剩下的序列有一个长度最大的连续递增子序列。
思路:首先这里最容易想到,枚举任意两个点j,i,删掉从j到i的序列,求剩下最大连续递增的子序列长度.i,j可以O(n)预处理,求出j处结尾的最长连续递增序列长度l[j],和i处起始的最长连续递增序列的长度r[i].这样得到一个O(n^2)的算法。
然而,n 200000的大小,还可以做到更好。对于j,i,我们先固定i后,要在他前面找到一个l[j]最大的j的时候,能不能不用扫一遍?
《算法入门经典》上的做法是按照A[j]的大小排成一个有序表,同时l[j]的大小也是有序的,我们直接二分当前的值在A[j]的有序表里,就可以知道满足条件(A[x]
思考这里就会发现,这里求在当前位置前最长的连续递增序列的过程,就是动态规划里典型的问题求最长上升子序列的过程。可以用二分将O(n^2)算法优化O(nlgn)。设dp[i]表示最长连续递增序列长度为i的最小A[i]值。注意:这里每当当前A[i]求完后,对他的l[i]在dp[]里更新:dp[l[i]]=min(dp[l[i]],A[i]);
思路:首先这里最容易想到,枚举任意两个点j,i,删掉从j到i的序列,求剩下最大连续递增的子序列长度.i,j可以O(n)预处理,求出j处结尾的最长连续递增序列长度l[j],和i处起始的最长连续递增序列的长度r[i].这样得到一个O(n^2)的算法。
然而,n 200000的大小,还可以做到更好。对于j,i,我们先固定i后,要在他前面找到一个l[j]最大的j的时候,能不能不用扫一遍?
《算法入门经典》上的做法是按照A[j]的大小排成一个有序表,同时l[j]的大小也是有序的,我们直接二分当前的值在A[j]的有序表里,就可以知道满足条件(A[x]
#include<bits/stdc++.h> using namespace std; const int maxn=200000+10; int n,a[maxn],f[maxn],g[maxn]; struct Candidate{ int a,g; Candidate(int a,int b):a(a),g(b) {} bool operator <(const Candidate & rhs) const { return a<rhs.a; } }; set<Candidate> s; int main() { int T;scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d",&a[i]); if(n==1){printf("1\n");continue;} f[n-1]=1; for(int i=n-2;i>=0;i--){ if(a[i]<a[i+1]) f[i]=f[i+1]+1; else f[i]=1; } g[0]=1; for(int i=1;i<n;i++){ if(a[i]>a[i-1]) g[i]=g[i-1]+1; else g[i]=1; } s.clear(); s.insert(Candidate(a[0],g[0])); int ans=1; for(int i=1;i<n;i++){ Candidate c(a[i],g[i]); set<Candidate>::iterator it=s.lower_bound(c); bool keep=true; if(it!=s.begin()){ Candidate last=*(--it); int len=f[i]+last.g; ans=max(ans,len); if(c.g<=last.g) keep=false; } if(keep){ s.erase(c); s.insert(c); it=s.find(c); it++; while(it!=s.end()&&it->a>c.a&&it->g<=c.g) s.erase(it++); } } printf("%d\n",ans); } }
思考这里就会发现,这里求在当前位置前最长的连续递增序列的过程,就是动态规划里典型的问题求最长上升子序列的过程。可以用二分将O(n^2)算法优化O(nlgn)。设dp[i]表示最长连续递增序列长度为i的最小A[i]值。注意:这里每当当前A[i]求完后,对他的l[i]在dp[]里更新:dp[l[i]]=min(dp[l[i]],A[i]);
#include<bits/stdc++.h> using namespace std; const int maxn=200000,inf=99999; int r[maxn+10],l[maxn+10],a[maxn+10],dp[maxn+10]; int main() { int T;scanf("%d",&T); while(T--){ memset(r,0,sizeof(r)); memset(l,0,sizeof(l)); int n;scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); r =1; for(int i=n-1;i>=1;i--){ if(a[i]<a[i+1]) r[i]=r[i+1]+1; else r[i]=1; } l[1]=1; for(int i=2;i<=n;i++){ if(a[i]>a[i-1]) l[i]=l[i-1]+1; else l[i]=1; } for(int i=1;i<=n;i++) dp[i]=inf; int ans=0; for(int i=1;i<=n;i++){ int len=lower_bound(dp+1,dp+n+1,a[i])-dp; ans=max(ans,len+r[i]-1); dp[l[i]]=min(dp[l[i]],a[i]); } printf("%d\n",ans); } }
相关文章推荐
- 【转】js 获取浏览器高度和宽度值(多浏览器)
- jQuery数据存储的相关方法
- jQuery操作数组的工具方法
- jQuery核心函数
- html5-创建浮动框架
- 1234: ZJTZYRC筛offer(并查集 )
- echartsJS初探--图形报表
- CSS position属性详解
- JSON与fastjson
- 基于javascript实现图片滑动效果
- (二)认识标签(1)
- JavaScript中this的理解
- Understanding Asynchronous IO With Python 3.4's Asyncio And Node.js
- Node中的包和模块
- 《JavaScript Ninja》之闭包
- html5中的创建热点区域
- JS中数组对象去重
- jquery获取checkbox选中值为undefined
- [后端人员耍前端系列]AngularJs篇:30分钟快速掌握AngularJs
- 解析驾考json数据,将其写入word文件中