AtCoder Beginner Contest 272 E - Add and Mex(调和级数) (神智不清的一周)

赛后总结

这次d因为没看题目输出,一直wa。浪费太多时间了。
e试过 n l o g 2 n nlog^2n nlog2n,t麻了。

题意:

进行m此操作,每次操作对
a a a中的所有 i ∈ [ 1 , n ] i\in[1,n] i[1,n]执行 a [ i ] + i a[i] + i a[i]+i
每次操作完后,询问mex(最小的非负数,不在a中)。

思路:

我们首先可以一种特殊情况, a a a数组都是0.
a [ 1 ] a[1] a[1]
进行n次操作后,最后会超过n.
a [ 2 ] a[2] a[2]
进行 n 2 \frac{n}{2} 2n次操作后,最后会超过n.
a [ 3 ] a[3] a[3]
进行 n 3 \frac{n}{3} 3n次操作后,最后会超过n.

a [ n ] a[n] a[n]
进行 n n \frac{n}{n} nn次操作后,最后会超过n.


假如一个数超过了n,那么我们还要考虑它吗?
显然是不用。

对于n个数的mex,答案范围在 [ 0 , n ] [0,n] [0,n]总共n+1种可能

那么我们只用考虑 a [ i ] 在 [ 0 , n ] a[i]在 [0,n] a[i][0,n]中的时候,之后统计答案就好了。
那么总共要考虑的操作数
n + n / 1 + n / 2 + n / 3 + . . . + n / n n + n/1 + n/2 + n/3 + ...+n/n n+n/1+n/2+n/3+...+n/n
= n × ( 1 / 1 + 1 / 2 + 1 / 3 + . . . + 1 / n ) =n \times ( 1/1 + 1/2 + 1/3 + ...+1/n) =n×(1/1+1/2+1/3+...+1/n)
= n l o g n =nlogn =nlogn
上式是调和级数

做法:

  • 对每个 a [ i ] a[i] a[i]操作后,范围在 [ 0 , n ] [0,n] [0,n]中的时间点记录。
  • 在找mex时候,因为总共的操作数 n l o g n nlogn nlogn是这么多,所以可以暴力找。

AC

#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <algorithm>
#include <queue>
#include <stack>
#include <string>
#include <cmath>
#include <cstring>
#define For(i,x,y) for(int i = (x); i <= (y); i ++ )
#define fori(i,x,y) for(int i = (x); i < (y); i ++ )
#define sz(a) (int)a.size()
#define ALL(a) a.begin(), a.end()
#define mst(x,a) memset(x,a,sizeof(x))
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define fi first
#define se second
#define db double
#define endl '\n' 
#define debug(a) cout << #a << ": " << a << endl
using namespace std;
typedef long long LL;
typedef long long ll;
typedef unsigned long long ULL;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
typedef pair<int,int>pa;
typedef pair<ll,ll>pai;
typedef pair<db,db> pdd;
const db eps = 1e-6;
const db pi = acos(-1.0);

template<typename T1, typename T2> void ckmin(T1 &a, T2 b) { if (a > b) a = b; }
template<typename T1, typename T2> void ckmax(T1 &a, T2 b) { if (a < b) a = b; }
int read() {
    int x = 0, f = 0; char ch = getchar();
    while (!isdigit(ch)) f |= ch == '-', ch = getchar();
    while (isdigit(ch)) x = 10 * x + ch - '0', ch = getchar();
    return f ? -x : x;
}
template<typename T> void print(T x) {
    if (x < 0) putchar('-'), x = -x;
    if (x >= 10) print(x / 10);
    putchar(x % 10 + '0');
}
template<typename T> void print(T x, char let) {
    print(x), putchar(let);
}
template<class T> bool uin(T &a, T b) { return a > b ? (a = b, true) : false; }
template<class T> bool uax(T &a, T b) { return a < b ? (a = b, true) : false; }

const int maxn = 200000 + 6;

ll a[maxn];
vector<int> arriveTime[maxn];
int main() {
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
    int n, m;
    cin>>n>>m;
    for(int i = 1; i <= n; i++ ) {
        cin >> a[i];
        ll time = 1;
        if(a[i] < 0) {
            //cal
            ll dis = -a[i];
            time = (dis + i - 1)/i;
            a[i] += (time-1)*i;
        }
        if(time <= m ) {
            //possible
            for(int j = time; j <= m; j ++){
                a[i] += i;
                if(a[i] <= n) arriveTime[j].pb(a[i]);
                else break;
            }
        }
        
    }

    for(int i = 1; i <= m; i ++ ) {
        vector<bool> mex(arriveTime[i].size() + 1);
        for(int v: arriveTime[i]){
            if(v < mex.size()) mex[v] = 1;
        }
        int ans = 0;
        while(mex[ans])ans++;
        cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值