题解:P13499 「Cfz Round 6」Umiyuri Kaiteitan

\(40\) 分做法

由于最终求的是每个文件包含的字符数量,所以并不需要记录每个文件名与顺序,只需要记录文件名的长度之和即可。

我们用 \(ans_i\) 表示文件 \(i\) 包含的字符数量,\(vis_i\) 表示文件 \(i\) 是否被创建,\(cnt\) 表示目前文件名的总长度(包括相邻两个文件名之间的空格)。每当执行一条指令时,先通过 \(vis\) 数组来检测文件是否存在,若不存在则标记 \(vis_i = 1\) 并将 \(cnt\) 加上 \(2\)(文件名长度加上一个空格的长度),更新文件名总长度;然后把 \(ans_i\) 设为 \(cnt\),即文件 \(i\) 在写入后的大小。

注意,上面的计数方法有个小漏洞:\(cnt\) 会在结尾多记录一个空格。解决办法很简单,可以在第一次操作时把 \(cnt\) 减一,或者更新文件大小时把 \(ans_i\) 设为 \(cnt - 1\) 即可。

于是,我们得到代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int n,m,ans[maxn];
bool vis[maxn];

int main(){
    cin>>n>>m;
    int a,cnt=0;
    for(int i=1;i<=n;++i){
        cin>>a;

        //文件不存在,更新 vis 和 cnt
        if(!vis[a]){
            vis[a]=1;
            cnt+=2;
        }

        //进行写入操作
        ans[a]=cnt-1;
    }
    for(int i=1;i<=m;++i){
        cout<<ans[i]<<' ';
    }
    return 0;
}

提交,嗯?\(40\) 分?

\(100\) 分做法

测一下样例二,就会发现,这份代码计算出的第六个和第十个文件大小计算错误。这是为什么呢?

其实,我们忽略了一个问题:文件名不一定只有一位数,可能是两位数甚至更多。这时,将 \(cnt\) 加上 \(2\) 就不对了,正确做法是加上 \(len + 1\)\(len\) 表示文件名长度,\(1\) 是一个空格的长度)。

我们要再写一个函数,用来获取文件名长度(也就是文件名的位数)。这样就得出了满分代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+5;
int n,m,ans[maxn];
bool vis[maxn];

//获取文件名长度
int get(int x){
    int sum=0;
    while(x){
        x/=10;
        ++sum;
    }
    return sum;
}

int main(){
    cin>>n>>m;
    int a,cnt=0;
    for(int i=1;i<=n;++i){
        cin>>a;

        //文件不存在,更新 vis 和 cnt
        if(!vis[a]){
            vis[a]=1;
            cnt+=get(a);
            ++cnt;
        }

        //进行写入操作
        ans[a]=cnt-1;
    }
    for(int i=1;i<=m;++i){
        cout<<ans[i]<<' ';
    }
    return 0;
}
posted @ 2025-07-27 18:28  noiiloveyou  阅读(9)  评论(0)    收藏  举报