[NOIP2013] 花匠
2018-06-18 00:00:19来源:未知 阅读 ()
初看这道题想到O(n2) 的暴力dp
用f[i][0]表示取第i个点为最低点时的答案, f[i][1]为最高点,且f[i][0] = max( f[j][1] ) +1
这样每次都要查询前面区间满足 h[i]>h[j] 的最大值, 可以考虑 线段树区间查询 或者 BIT 或者BST , 时间降至O(nlogn)
但是BIT时要注意查询h[i]<h[j] 条件时涉及到 j ~ maxheight 的最值查询, 可以把maxheight -h[i] +2 (BIT下标不为0) 存入树状数组
RE 代码:BIT 误取最大下标为n!! 实际上应该在读入时求出maxheight!!
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> #include<queue> #include<stack> #include<map> #include<set> #include<string> #include<iomanip> #include<ctime> #include<climits> #include<cctype> #include<algorithm> #ifdef WIN32 #define AUTO "%I64d" #else #define AUTO "%lld" #endif using namespace std; #define lowbit(x) x&-x #define smax(x,tmp) x=max(x,tmp) const int maxn=100005; const int INF=0x3f3f3f3f; int high[maxn],low[maxn];//!! LAST RE!!! BIT must be bigger!! maxheight!!! int f[maxn][2];//0: low point ; 1: high point int a[maxn]; int n; int maxheight=-INF; inline void add_low(int x,int val) { for(int i=x;i<=maxheight+1;i+=lowbit(i)) smax(low[i],val);//also easy to consider as n!! } inline void add_high(int x,int val) { for(int i=x;i<=maxheight+1;i+=lowbit(i)) smax(high[i],val); } inline int query_low(int x) { int ret=0; for(int i=x;i;i-=lowbit(i)) smax(ret,low[i]); return ret; } inline int query_high(int x) { int ret=0; for(int i=x;i;i-=lowbit(i)) smax(ret,high[i]); return ret; } int main() { freopen("flower.in","r",stdin); freopen("flower.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",a+i),smax(maxheight,a[i]); int ans=1; f[1][0]=f[1][1]=1; add_low(a[1]+1,f[1][0]);add_high(maxheight-a[1]+2,f[1][1]);//add reversely, to query the max !! for(int i=2;i<=n;i++) { f[i][0]=query_high(maxheight-a[i]+1)+1; f[i][1]=query_low(a[i])+1; add_low(a[i]+1,f[i][0]);//can't either!! add_high(maxheight-a[i]+2,f[i][1]);// mustn't use the 0 point !! smax(ans,max(f[i][0],f[i][1])); } printf("%d",ans); return 0; }
AC代码:(BIT)
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> #include<queue> #include<stack> #include<map> #include<set> #include<string> #include<iomanip> #include<ctime> #include<climits> #include<cctype> #include<algorithm> #ifdef WIN32 #define AUTO "%I64d" #else #define AUTO "%lld" #endif using namespace std; #define lowbit(x) x&-x #define smax(x,tmp) x=max(x,tmp) const int maxn=100005; const int maxh=1000005; const int INF=0x3f3f3f3f; int high[maxh],low[maxh];//for BIT int f[maxn][2];//0: low point ; 1: high point int a[maxn]; int n; int maxheight=-INF; inline void add_low(int x,int val) { for(int i=x;i<=maxheight+1;i+=lowbit(i)) smax(low[i],val); } inline void add_high(int x,int val) { for(int i=x;i<=maxheight+1;i+=lowbit(i)) smax(high[i],val); } inline int query_low(int x) { int ret=0; for(int i=x;i;i-=lowbit(i)) smax(ret,low[i]); return ret; } inline int query_high(int x) { int ret=0; for(int i=x;i;i-=lowbit(i)) smax(ret,high[i]); return ret; } int main() { freopen("flower.in","r",stdin); freopen("flower.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",a+i),smax(maxheight,a[i]); int ans=1; f[1][0]=f[1][1]=1; add_low(a[1]+1,f[1][0]);add_high(maxheight-a[1]+2,f[1][1]);//add reversely, to query the max !! for(int i=2;i<=n;i++) { f[i][0]=query_high(maxheight-a[i]+1)+1; f[i][1]=query_low(a[i])+1; add_low(a[i]+1,f[i][0]);//can't either!! add_high(maxheight-a[i]+2,f[i][1]);// mustn't use the 0 point !! smax(ans,max(f[i][0],f[i][1])); } printf("%d",ans); return 0; } //O(n): f[i][0,1] indicates that don't need to stop at i, but had the previous cases //O(n): find the corners with the tendency
现虑另一种 O(n) 的dp
用f[i][0,1] 表示 i 及其以前所有高度的最大值,但是0 表示之前出于下降阶段而并非之前的上一个节点为转折点, 仅仅表示一个趋势
另一种 o(n) 算法
由于一段相同变化趋势的区段内只能留下一个端点
故只需要统计出所有的”拐点“即可!
WA代码: 只考虑到相邻的几个数,但是缺乏长远的考虑!!!!应用趋势来判断!!
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> #include<queue> #include<stack> #include<map> #include<set> #include<string> #include<iomanip> #include<ctime> #include<climits> #include<cctype> #include<algorithm> #ifdef WIN32 #define AUTO "%I64d" #else #define AUTO "%lld" #endif using namespace std; #define lowbit(x) x&-x #define smax(x,tmp) x=max(x,tmp) const int maxn=100005; const int INF=0x3f3f3f3f; int n; int a[maxn]; int main() { freopen("flower.in","r",stdin); freopen("flower.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",a+i); int ans=2; for(int i=2;i^n;i++) { if(a[i-1]>a[i] && a[i]<a[i+1]) ans++;//Last WA!! not only the near one, but long trems if(a[i-1]<a[i] && a[i]>a[i+1]) ans++; } printf("%d",ans); return 0; }
AC代码:
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<vector> #include<queue> #include<stack> #include<map> #include<set> #include<string> #include<iomanip> #include<ctime> #include<climits> #include<cctype> #include<algorithm> #ifdef WIN32 #define AUTO "%I64d" #else #define AUTO "%lld" #endif using namespace std; #define lowbit(x) x&-x #define smax(x,tmp) x=max(x,tmp) const int maxn=100005; const int INF=0x3f3f3f3f; int n; int a[maxn]; int main() { freopen("flower.in","r",stdin); freopen("flower.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",a+i); int ans=1;//indicates the first one to start!! int flag=0;//indicates start!! for(int i=1;i^n;i++) { if(a[i]<a[i+1] && (flag==0 || flag==-1)) flag=1,ans++; if(a[i]>a[i+1] && (flag==0 || flag==1)) flag=-1,ans++; } printf("%d",ans); return 0; }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- NOIP 2013 花匠 神仙操作 2019-05-13
- 2018/7/16 YMOI模拟 NOIP2013D2T3华容道 2018-07-17
- NOIP2013Day1T3 表示只能过一个点 2018-06-17
- NOIP2013 货车运输 [LCA+最大生成树] 2018-06-17
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash