NOIP2013 花匠 dp/贪心
来源:互联网 发布:旅行商问题算法matlab 编辑:程序博客网 时间:2024/05/29 12:50
【问题描述】
——————————————————————————————————————————
类似于单调子序列问题,不难发现可以dp。
f(i)表示以i结尾能够满足条件1的最多的花的数量
f(i)=max{ f(j) | f(j)%2==0 && h[j] > h[i] || f(j)%2==1 && h[j] < h[i]}+1
g(i)表示以i结尾能够满足条件2的最多的花的数量
g(i)=max{ g(j) | g(j)%2==0 && h[j] < h[i] || g(j)%2==1 && h[j] > h[i] } + 1
f(1)=g(1)=1;
线段树维护花的高度,可以离散化,分别对于两个要求建上两颗线段树,每个线段树维护两个数组,分别是f(i)%2==0的最大值和f(i)%2==1的最大值。
还算是比较水了,是半道代码题?(表述十分滑稽)
AC代码(dp):
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#include<set>#include<map>#include<cctype>#include<vector>#include<ctime>using namespace std;const int maxn=100005;int N,h[maxn];int f[maxn],g[maxn];int a[maxn],rank[maxn],MAX;int rt,lc[maxn<<1],rc[maxn<<1],maxv0[maxn<<1],maxv1[maxn<<1],np;void _scanf(int &x){ x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();}void data_in(){ _scanf(N); for(int i=1;i<=N;i++) _scanf(h[i]);}void ready(){ memcpy(a,h,sizeof(a)); sort(a+1,a+N+1); int cnt=unique(a+1,a+N+1)-a; for(int i=1;i<=N;i++) rank[i]=lower_bound(a+1,a+cnt+1,h[i])-a; memcpy(h,rank,sizeof(h)); for(int i=1;i<=N;i++) MAX=max(MAX,h[i]);}void set_segtree(int &now,int L,int R){ now=++np; if(L==R) return; int m=L+R>>1; set_segtree(lc[now],L,m); set_segtree(rc[now],m+1,R);}void update(int now,int L,int R,int x,int v){ if(L==R && L==x) { if(v%2==0) maxv0[now]=v; else maxv1[now]=v; return; } int m=L+R>>1; if(x<=m) update(lc[now],L,m,x,v); else update(rc[now],m+1,R,x,v); if(v%2==0) maxv0[now]=max(maxv0[lc[now]],maxv0[rc[now]]); if(v%2==1) maxv1[now]=max(maxv1[lc[now]],maxv1[rc[now]]);}int query0(int now,int L,int R,int x,int y){ if(x<=L && R<=y) return maxv0[now]; int m=L+R>>1; if(y<=m) return query0(lc[now],L,m,x,y); if(x>m) return query0(rc[now],m+1,R,x,y); return max(query0(lc[now],L,m,x,y),query0(rc[now],m+1,R,x,y));}int query1(int now,int L,int R,int x,int y){ if(x<=L && R<=y) return maxv1[now]; int m=L+R>>1; if(y<=m) return query1(lc[now],L,m,x,y); if(x>m) return query1(rc[now],m+1,R,x,y); return max(query1(lc[now],L,m,x,y),query1(rc[now],m+1,R,x,y));}void dp1(){ f[1]=1; update(rt,0,MAX,h[1],f[1]); for(int i=2;i<=N;i++) { int t0=0,t1=0; if(h[i]!=MAX) t0=query0(rt,0,MAX,h[i]+1,MAX); if(h[i]!=0) t1=query1(rt,0,MAX,0,h[i]-1); f[i]=max(t0,t1)+1; update(rt,0,MAX,h[i],f[i]); }}void dp2(){ g[1]=1; update(rt,0,MAX,h[1],g[1]); for(int i=2;i<=N;i++) { int t0=0,t1=0; if(h[i]!=0) t0=query0(rt,0,MAX,0,h[i]-1); if(h[i]!=MAX) t1=query1(rt,0,MAX,h[i]+1,MAX); g[i]=max(t0,t1)+1; update(rt,0,MAX,h[i],g[i]); }}void work100(){ ready(); set_segtree(rt,0,MAX); dp1(); np=rt=0; memset(lc,0,sizeof(lc)); memset(rc,0,sizeof(rc)); memset(maxv0,0,sizeof(maxv0)); memset(maxv1,0,sizeof(maxv1)); set_segtree(rt,0,MAX); dp2(); int ans=0; for(int i=1;i<=N;i++) ans=max(ans,max(f[i],g[i])); printf("%d\n",ans);}int main(){ freopen("test.in","r",stdin); freopen("test.out","w",stdout); data_in(); work100(); return 0;}
话说我还说了贪心是吧?
实际上思路还是很简单,对于一段连续上升或下降的序列,删除除去最高点和最低点以外的中间点,剩下的点的数量就是答案(实际上也就是拐点的数量,第一株花一定是留下来的,最后一株花如果不和倒数第二株花一样高也要留下来)。
AC代码(贪心):
#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>#include<queue>#include<set>#include<map>#include<cctype>#include<vector>#include<ctime>using namespace std;const int maxn=100005;int N,h[maxn];void _scanf(int &x){ x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();}void data_in(){ _scanf(N); for(int i=1;i<=N;i++) _scanf(h[i]);}void work100(){ int ans=0; int ok=-1;//0表示原先是下降,1表示原先是上升 for(int i=2;i<=N;i++) { if(h[i]==h[i-1]) continue; if(h[i]>h[i-1]) { if(ok!=1) ans++; ok=1; } if(h[i]<h[i-1]) { if(ok!=0) ans++; ok=0; } } if(h[N]!=h[N-1] && N!=1) ans++; printf("%d\n",ans);}int main(){ freopen("test.in","r",stdin); freopen("test.out","w",stdout); data_in(); work100(); return 0;}
阅读全文
0 0
- 【noip2013】花匠 DP||贪心
- NOIP2013 花匠 dp/贪心
- NOIP2013 花匠 [dp] [贪心] [BIT]
- 贪心 NOIP2013 花匠
- 洛谷 1970 [NOIP2013] 花匠 贪心
- NOIP2013 花匠 解题报告(贪心)
- [NOIP2013] 花匠&积木大赛 贪心水题
- Noip2013 Day2 T2 花匠(贪心)
- [NOIP2013][vijos1845]花匠(dp+bit)
- [NOIP2013]花匠
- NOIP2013花匠
- NOIP2013 花匠
- NOIP2013 花匠
- NOIP2013花匠
- NOIP2013 花匠
- 【NOIP2013】花匠
- noip2013花匠
- 【noip2013】花匠
- 《java 多线程编程核心技术》读书笔记六
- tensorflow笔记(四)之MNIST手写识别系列一
- 51nod1256 乘法逆元
- 分布式系列 Two phase commit protocol (5-上)
- ANR 定位和修正
- NOIP2013 花匠 dp/贪心
- Linux I2C驱动完全分析(二)
- POJ
- Ubuntu 12.04更新源地址列表更改方法
- Filter(过滤器)
- RN实现ListView
- IndexerApplication
- launch mode 应用场景
- Android 调试安装apk 报错 Installation error: INSTALL_FAILED_INSUFFICIENT_STORAGE