首页 > 代码库 > YYH的苍天大竹(NOIP模拟赛Round 6)
YYH的苍天大竹(NOIP模拟赛Round 6)
原题传送门
这道题我们很显然要用DP来做。
那么首先我们需要构造出一个DP方程
f[i]肯定由另一个状态dp转移后+1得到,那么这个状态是什么呢?
很明显就是mint[i]~i-k(在此mint表示的是以i为结尾的竹子最左端最多能延展到的位置)
看到这个之后我们想到了一个N^2DP
但是还是不够
我们想一想如何得到mint?
mint就是判断一段区间的最大值减去最小值是否满足题意
那么我们可不可以用数据结构得出这个答案呢?
显然我们可以用线段树来优化这个过程
时间复杂度O(nlogn)
同样在得出答案的过程我们也可以用线段树加速
下面贴代码
#include<cstdio> #include<cstring> #define inf 0x3f3f3f3f #define min(x,y) (x<y?x:y) #define max(x,y) (x>y?x:y) using namespace std; int a[100005]; struct mm{ int v1,v2; }t[300005]; int mint[100005]; int f[300005]; int m=1,n,s,l; void pushdown(int i){t[i].v1=min(t[i<<1].v1,t[i<<1|1].v1);t[i].v2=max(t[i<<1].v2,t[i<<1|1].v2);} void buildtree(){ while(m<n+2)m<<=1; for(int i=1;i<=n;i++) t[i+m].v1=t[i+m].v2=a[i]; for(int i=m-1;i;i--) pushdown(i); } int query(int l,int r) { int maxn=-inf,minn=inf; for(l=l+m-1,r=r+m+1;l^r^1;l>>=1,r>>=1) { if(~l&1)minn=min(minn,t[l^1].v1),maxn=max(maxn,t[l^1].v2); if(r&1)minn=min(minn,t[r^1].v1),maxn=max(maxn,t[r^1].v2); } return maxn-minn; } int que(int l,int r) { int minn=inf; for(l+=m-1,r+=m+1;l^r^1;l>>=1,r>>=1) { if(~l&1)minn=min(minn,f[l^1]); if(r&1)minn=min(minn,f[r^1]); } return minn; } void push(int x){f[x]=min(f[x<<1],f[x<<1|1]);} void add(int x,int y){for(f[x+=m]=y,x>>=1;x;x>>=1)push(x);} int main(){ memset(f,127/3,sizeof(f)); scanf("%d%d%d",&n,&s,&l);n++; for(int i=2;i<=n;i++)scanf("%d",&a[i]); a[1]=a[2]; buildtree(); int le=1; for(int i=1;i<=n;i++) { int tmp=query(le,i); while(tmp>s) { tmp=query(++le,i); } mint[i]=le; } add(1,0); for(int i=2;i<=n;i++) if(max(1,mint[i]-1)>i-l)add(i,inf); else add(i,que(max(1,mint[i]-1),i-l)+1); printf("%d\n",f[n+m]>=inf?-1:f[n+m]); return 0; }
YYH的苍天大竹(NOIP模拟赛Round 6)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。