NOIP2018 普及组复赛题解

本次也是天天快乐编程集训队2021CSP&NOIP赛前训练-赛前适应赛的题目,OI赛制有步骤分,请大家放心书写代码。
2018年一等奖浙江分数线为230分,二等奖分数线为100分,三等奖分数线为80分。
当年附中情况,zxy是163分
对应luogu题目, T1 标题统计T2 龙虎斗T3 摆渡车T4 对称二叉树 ,可以到luogu上查看更多题解。

T1 标题统计 字符串

需要读取一行,即gets或者getline。
判断数字和字母大小写就是满分了

第一题比较送分,一般情况下第一题最简单,是签到题。但是如果第一题比较难,应该先做后面的,比赛时间有限。

正式比赛需要注意这个题目概况,这个题需要我们在相应的文件夹内将文件名命名为title.cpp,并在代码中添加上文件读写。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    freopen("title.in","r",stdin);
    freopen("title.out","w",stdout);
    //你的代码
    return 0;
}

T2 龙虎斗 枚举、预处理

枚举,p1位置加s1个工兵,然后依次枚举把s2个工兵放在所有的兵营里,每次算一遍双方势力之差,取最小就可以了
直接枚举,可以得到80分

#include <bits/stdc++.h>
using namespace std;
int n,m, p1, s1, s2;
int a[1000005];

//计算双方势力之差
int cal(int x)
{
    //sum1计算左边,sum2计算右边    
    int sum1 = 0, sum2 = 0; 
    //先假设位置x加上s2个工兵
    a[x] += s2;                
    for (int i = 1; i <= n; i++)
    {
        //m号兵营跳过
        if (i == m)
            continue; 
        //分左右
        else if (i < m)
            sum1 += (m - i) * a[i];
        else
            sum2 += (i - m) * a[i];
    }
    //再减去s2个,因为是假设加上了s2个工兵
    a[x] -= s2;
    if (sum1 >= sum2)
        return sum1 - sum2;
    return sum2 - sum1;
}
int main()
{
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
        scanf("%d", &a[i]);
    scanf("%d%d%d%d", &m, &p1, &s1, &s2);
    //加上s1个工兵
    a[p1] += s1;
    int min = 1e9,ans;
    //枚举编号i
    for (int i = 1; i <= n; i++)
    {
        //算一下势力之差
        int tmp = cal(i); 
        //小的话要更新
        if (min > tmp)
        { 
            min = tmp;
            ans = i;
        }
    }
    printf("%d", ans);
    return 0;
}

之前的代码是超时的,因为做法是O(n^2 )的,但是后20%数据是10^5 ,写起来要难写些。而且预处理会爆int,当求和是一定要计算好数据类型是否够用,因为比赛没有OJ帮忙验证。
其实就是做下前缀和

T3 摆渡车 动态规划(高级)

这题比想像得要难,dp[i][j]表示第i个人等了j分钟的最优值 ,

T4 对称二叉树 二叉树

这题反而没想象的那么难,直接dfs就好了

posted @ 2021-09-25 11:32  暴力都不会的蒟蒻  阅读(483)  评论(0编辑  收藏  举报