【2019.10.4】NOIP2019模拟训练题
总结
T1 想的时间太久了(1h30min),思路是完全正确的,但对dp本身理解和练习还不够就没打,时间复杂度倒是分析出来了。
T2 贪心(我打的更像模拟)就直接过了,没用二分。30min左右就打完了。
T3 10分应该能拿到。卡在T1上所以完全抛掉了。
总的来说,一眼就可以看出哪些题比较可做,当然还是要花点时间稍微分析一下,以防能做的题以为不能做。先把可做的题分析好,打出来,不可做的题打打暴力拿一些部分分。
T1.
区间dp,破环成链是基本操作,预处理g数组。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define For(i,l,r) for(int i=l;i<=r;i++) #define DFor(i,r,l) for(int i=r;i>=l;i--) #define ll long long #define ri register int using namespace std; const int M=666; ll n,a[M],f[M][M],g[M][M],ans; bool b[M]; inline ll read(){ ll f=1,sum=0; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();} return f*sum; } inline void sets(){ For(i,1,n) g[i][i]=1; For(i,1,n-1){ memset(b,0,sizeof(b)); b[a[i]]=1; For(j,i+1,n){ if(b[a[j]]) g[i][j]=g[i][j-1]; else b[a[j]]=1,g[i][j]=g[i][j-1]+1; } } } int main(){ freopen("merge.in","r",stdin); freopen("merge.out","w",stdout); n=read(); For(i,1,n) a[i]=read(),a[n+i]=a[i]; n<<=1; sets(); DFor(i,n-1,1){ For(j,i+1,n){ For(k,i,j-1){ f[i][j]=max(f[i][j],f[i][k]+f[k+1][j]+g[i][k]*g[k+1][j]); } } } For(i,1,n) ans=max(ans,f[i][i+(n>>1)-1]); printf("%lld",ans); return 0; }
T2.
(拿完部分分我就跑)40分的特殊点好像很好拿的样子→(突然发现)Ci=0的情况考虑下Ci非零会被淹死不就可以了吗,时间复杂度不会算,80分总是有的吧→(考完后)听说要用二分完了我挂了→(看到成绩)AK了??
直接丢代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define For(i,l,r) for(int i=l;i<=r;i++) #define DFor(i,r,l) for(int i=r;i>=l;i--) #define ll long long #define ri register int using namespace std; const int M=1e5+5; ll n,l,c[M],ans,wall,ea[M],cnt=1; bool fb,fc; struct node{ ll a,b,u; }e[M]; inline ll read(){ ll f=1,sum=0; char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){sum=(sum<<1)+(sum<<3)+(ch^48);ch=getchar();} return f*sum; } inline ll cmpa(node x,node y) {return x.a>y.a;} inline ll cmpp(node x,node y) {return x.u==y.u?x.a<y.a:x.u>y.u;} inline ll cmpea(ll x,ll y) {return x>y;} int main(){ freopen("climb.in","r",stdin); freopen("climb.out","w",stdout); n=read(),l=read(); For(i,1,n){ e[i].a=read();e[i].b=read();e[i].u=e[i].a-e[i].b; ea[i]=e[i].a; if(e[i].b) fb=1; } For(i,1,n){ c[i]=read(); if(c[i]) fc=1; } if(!fb){//no fall sort(e+1,e+n+1,cmpa); For(i,1,n){ ans+=e[i].a; wall+=c[i]; if(ans<0){ printf("-1"); return 0; } if(ans>=l){ printf("%d",i); return 0; } if(ans<=wall){ printf("-1"); return 0; } } printf("-1"); return 0; } if(!fc){//no wall sort(e+1,e+n+1,cmpp); sort(ea+1,ea+n+1,cmpea); For(i,1,n){ if(ans<0){ printf("-1"); return 0; } if(ans+ea[1]>=l){ printf("%d",i); return 0; } ans+=e[i].u; if(ea[1]==e[i].a){ ea[1]=ea[++cnt]; } } printf("-1"); return 0; } sort(e+1,e+n+1,cmpp); sort(ea+1,ea+n+1,cmpea); For(i,1,n){ if(ans+ea[1]>=l){ printf("%d",i); return 0; } ans+=e[i].u; wall+=c[i]; if(ans<=wall){ printf("-1"); return 0; } if(ans<0){ printf("-1"); return 0; } if(ea[1]==e[i].a){ ea[1]=ea[++cnt]; } } printf("-1"); return 0; }