NOIP2018普及组解题报告

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sugar_free_mint/article/details/84992735

凉凉记

洛谷 5015 标题统计

代码(题目过水)

#include <cstdio>
#include <cctype>
using namespace std;
int ans; char c;
int main(){
    while ((c=getchar())!=EOF) ans+=isalnum(c)>0;
    return !printf("%d",ans);
}

洛谷 5016 龙虎斗

题目链接

分析

有许多蒟蒻都漏掉了m号的情况,结果可能就与一等奖失之交臂,思路就是对于每一个节点判断最小值。(我朋友竟然打了二分,与一等奖失之交臂,当然,这是后话)


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
typedef long long bnt;
const int N=100010;
int n,m,choi,a[N+1],ans; bnt ans1,ans2,sum;
inline int iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    return ans;
}
int main(){
    n=iut(); for (rr int i=1;i<=n;++i) a[i]=iut();
    m=iut(); rr int x=iut(); a[x]+=iut(); choi=iut();
    for (rr bnt i=1;i<m;++i) ans1+=(m-i)*a[i];
    for (rr bnt i=m+1;i<=n;++i) ans2+=(i-m)*a[i];
    ans=m; sum=ans1<ans2?ans2-ans1:ans1-ans2;//m号初始化
    for (rr bnt i=1;i<m;++i){//轩轩
        ans1+=(m-i)*choi;
        rr bnt t=ans1<ans2?ans2-ans1:ans1-ans2;
        if (t<sum) sum=t,ans=i;
        ans1-=(m-i)*choi;
    }
    for (rr bnt i=m+1;i<=n;++i){//凯凯
        ans2+=(i-m)*choi;
        rr bnt t=ans1<ans2?ans2-ans1:ans1-ans2;
        if (t<sum) sum=t,ans=i;
        ans2-=(i-m)*choi;
    }
    printf("%d",ans);
    return 0;
}

洛谷 5017 摆渡车

题目链接

分析(线性dp)

作为这套题最难的一道题,我差点悲剧,不过这道题是一道dp的题目,设 d p [ i ] [ j ] dp[i][j] 表示第 i i 个同学(排序后)等车 j j 分钟后的最短等待时间,那么在同一段的时候 d p i , j = d p i 1 , t i t i 1 + j + j dp_{i,j}=dp_{i-1,t_i-t_{i-1}+j}+j
要新开一段的时候 d p i , j = m i n t i 1 + k + m t i + j { d p i 1 , k } + j dp_{i,j}=min_{t_{i-1}+k+m\leq t_i+j}\{dp_{i-1,k}\}+j
直到现在,时间复杂度已经是 O ( n m 2 ) O(nm^2) ,已经比较高效了,但是按照dalao的思路,可以用前缀最小值优化 k k 的时间,优化至 O ( n m ) O(nm)


代码(线性dp)

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
#define min(a,b) (((a)<(b))?(a):(b))
using namespace std;
int dp[2][201],ans=1e8,n,m,a[501];
inline int iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    return ans;
}
int main(){
    n=iut(); m=iut();
    for (rr int i=1;i<=n;++i) a[i]=iut();
    sort(a+1,a+1+n);
    for (rr int i=1;i<=n;++i){
    	dp[i&1][0]=1e8;
    	for (rr int j=0;j<=min(a[i]-a[i-1]-m,m-1);++j) dp[i&1][0]=min(dp[i&1][0],dp[1-(i&1)][j]);
        for (rr int j=1;j<2*m;++j){
        	dp[i&1][j]=dp[i&1][j-1];//前缀最小值
        	if (a[i]-a[i-1]+j>=m&&a[i]-a[i-1]+j<3*m)
            dp[i&1][j]=min(dp[i&1][j],dp[1-(i&1)][a[i]-a[i-1]+j-m]);//新开一段
        }
        for (rr int j=0;j+a[i]-a[i-1]<2*m;++j)
            dp[i&1][j]=min(dp[i&1][j],dp[1-(i&1)][j+a[i]-a[i-1]]);//同一段
        for (rr int j=0;j<2*m;++j) dp[i&1][j]+=j;//无论开不开都要加等待时间
    }
    for (rr int i=0;i<m;++i) ans=min(ans,dp[n&1][i]);//取最小值
    return !printf("%d",ans);
}

分析(斜率优化)

斜率优化与上面的线性dp迥然不同,而且对于 O ( n m ) O(nm) 这么小的情况下, O ( m a x { t i } ) O(max\{t_i\}) 太大了,不过为了培养更多的思维,在此讲一下斜率优化的方法(肯定非高效正解)
d p [ i ] dp[i] 表示到第 i i 时刻的总等待时间, c n t [ i ] cnt[i] 表示到第 i i 时刻的同学个数, s u m [ i ] sum[i] 表示在第 i i 时刻时发车的总等待时间
那么 d p [ i ] = m i n { d p [ j ] + ( c n t [ i ] c n t [ j ] ) i ( s u m [ i ] s u m [ j ] ) } dp[i]=min\{dp[j]+(cnt[i]-cnt[j])*i-(sum[i]-sum[j])\}
然而这样肯定会超时,若使 k ( j &lt; k ) k(j&lt;k) 更优秀,那么
d p [ k ] + ( c n t [ i ] c n t [ k ] ) i ( s u m [ i ] s u m [ k ] ) &lt; d p [ j ] + ( c n t [ i ] c n t [ j ] ) i ( s u m [ i ] s u m [ j ] ) dp[k]+(cnt[i]-cnt[k])*i-(sum[i]-sum[k])&lt;dp[j]+(cnt[i]-cnt[j])*i-(sum[i]-sum[j])
根据一次函数 y = k x + b y=kx+b 可以得到
d p [ k ] d p [ j ] + s u m [ k ] s u m [ j ] c n t [ k ] c n t [ j ] &lt; i \frac{dp[k]-dp[j]+sum[k]-sum[j]}{cnt[k]-cnt[j]}&lt;i
因为 i i 是单调递增的,所以说需要维护下凸壳


代码(斜率优化)

#include <cstdio>
#include <cctype>
#include <algorithm>
#define rr register
#define min(a,b) (((a)<(b))?(a):(b))
using namespace std;
int dp[4000201],ans=1e8,n,m,T,cnt[4000201],sum[4000201],l=1,r,q[4000201];
inline int iut(){
    rr int ans=0; rr char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    return ans;
}
signed main(){
    n=iut(); m=iut();
    for (rr int i=1;i<=n;++i){
    	rr int x=iut(); T=max(T,x);
    	++cnt[x]; sum[x]+=x;
    }
    for (rr int i=1;i<=T+m;++i) cnt[i]+=cnt[i-1],sum[i]+=sum[i-1];
    for (rr int i=0;i<m-1;++i) dp[i]=cnt[i]*i-sum[i];
    for (rr int i=m-1;i<=T+m;++i){
        while (l<r&&(dp[q[l+1]]-dp[q[l]]+sum[q[l+1]]-sum[q[l]])<=i*(cnt[q[l+1]]-cnt[q[l]])) ++l;//排除队头
        dp[i]=cnt[i]*i-sum[i];//特殊情况
        if (l<=r) dp[i]=min(dp[i],dp[q[l]]+(cnt[i]-cnt[q[l]])*i-(sum[i]-sum[q[l]]));//正常的dp方程
        while (l<r&&(dp[q[r]]-dp[q[r-1]]+sum[q[r]]-sum[q[r-1]])*(cnt[i-m+1]-cnt[q[r]])>=(dp[i-m+1]-dp[q[r]]+sum[i-m+1]-sum[q[r]])*(cnt[q[r]]-cnt[q[r-1]])) --r;//排除队尾
        q[++r]=i-m+1;//只有得到第i个,才能插入i-m+1
    }
    for (rr int i=T;i<=T+m;++i) ans=min(ans,dp[i]);
    return !printf("%d",ans);
}

洛谷 5018 对称二叉树

题目链接

分析

一开始我以为暴力过不了,没想到时间复杂度是 O ( n l o g n ) O(nlogn) ,结果成功垫底(可能是因为均摊的原因)
中序+manacher我不会


代码

#include <cstdio>
#include <cctype>
#define rr register
#define max(a,b) (((a)>(b))?(a):(b))
using namespace std;
const int N=1000000;
int n,a[N+1],lson[N+1],rson[N+1],ans;
inline signed iut(){
    rr int ans=0,f=1; rr char c=getchar();
    while (!isdigit(c)&&c!='-') c=getchar();
    if (c=='-') c=getchar(),f=-f;
    while (isdigit(c)) ans=(ans<<3)+(ans<<1)+c-48,c=getchar();
    return ans*f;
}
inline signed check(int x,int y){
    if (x==-1&&y==-1) return 1;
    if (a[x]!=a[y]) return 0;
    return check(rson[x],lson[y])&&check(lson[x],rson[y]);
}
inline signed dfs(int x){
    rr int siz=1;
    if (lson[x]!=-1) siz+=dfs(lson[x]);
    if (rson[x]!=-1) siz+=dfs(rson[x]);
    if (check(lson[x],rson[x])) ans=max(ans,siz);
    return siz;
}
signed main(){
    scanf("%d",&n);
    for (rr int i=1;i<=n;++i) scanf("%d",&a[i]);
    for (rr int i=1;i<=n;++i) scanf("%d%d",&lson[i],&rson[i]);
    dfs(1);
    printf("%d",ans);
    return 0;
}

后续

突然发现第一第二题全对第四题输出1就可以在广东拿一等奖了

扫描二维码关注公众号,回复: 4522036 查看本文章

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/84992735