赛后总结
这次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;
}