1450D - Rating Compression
1450D 1800分
**题意:**给出一个数列A,通过A进行一些k ( k ∈ [ 1 , n ] ) (k \in [1,n]) (k∈[1,n])的构造B, b j = m i n j ≤ i ≤ j + k − 1 a i b_j = min_{j \le i \le j + k - 1}a_i bj=minj≤i≤j+k−1ai,问每个B数列是否为一个排列
一些想法:(乱七八糟不是正解
- 一个数如果比较小,并且出现多次,则需要一个长度起码能包含所有该数,该数才不会出现多次
- 一个数的影响范围为左右比它小的数内的范围,(于是我拿单调栈写了点,虽然写的好像是队列(很怪…
- 一个数如果不存在,则 b n − i + 1 b_{n - i + 1} bn−i+1后就不会再成立
发现还是很乱,而且有些情况没有考虑清楚:比如第一点我刚开始觉得所有数都是这样,其实只有当它比较小的时候,CF代码怎么会这么乱呢肯定不是正解(bu
先挖个坑,有点想不明白,(纪念一下我wa1的代码(?绝了)
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;
vector<int> g[maxn];
int mx[maxn];
int st[maxn];
int hh, tt;
int le[maxn], ri[maxn], a[maxn];
inline void init(int n) {
for(int i = 0; i <= n; ++ i) g[i].clear();
mx[0] = 0;
hh = 1, tt = 0;
}
int main() {
int T;
cin >> T;
while(T--) {
int n;
cin >> n;
init(n);
for(int i = 1; i <= n; ++i) {
cin >> a[i];
g[a[i]].push_back(i);
}
for(int i = 1; i <= n; ++i) {
while(hh <= tt && a[st[tt]] >= a[i]) --tt;
if(hh <= tt) le[i] = st[tt];
else le[i] = -1;
st[++tt] = i;
}
hh = 1, tt = 0;
for(int i = n; i >= 1; --i) {
while(hh <= tt && a[st[tt]] >= a[i]) --tt;
if(hh <= tt) ri[i] = st[tt];
else ri[i] = -1;
st[++tt] = i;
}
for(int i = 1; i <= n; ++i) {
cout << le[i] << " ";
}
cout << endl;
for(int i = 1; i <= n; ++i) {
cout << ri[i] << " ";
}
cout << endl;
for(int i = 1; i <= n; ++i) {
if(g[i].size() < 1) {
mx[i] = mx[i - 1];
continue;
}
//int len = g[i][g[i].size() - 1] - g[i][0] + 1;
int u = g[i][g[i].size() - 1];
int v = g[i][0];
int l = le[v];
int r = ri[u];
int len;
if(l == -1 && r == -1) {
len = u - v + 1;
}
else if(l == -1) {
len = r - v;
}
else if(r == -1) {
len = u - l;
}
else {
len = r - l - 2;
}
len = max(1, len);
mx[i] = max(mx[i - 1], len);
}
for(int i = 1; i <= n; ++i) {
cout << mx[i] << " ";
}
cout << endl;
int f = 0;
for(int i = 1; i <= n; ++i) {
if(g[i].size() == 0) {
if(f == 0) f = i;
}
if(f > 0 && n - i + 1 >= f) cout << 0;
else {
if(i >= mx[n - i + 1]) cout << 1;
else cout << 0;
}
}
cout << endl;
}
}
然后看题解去了,正解果然不长
k = 1,和 k = n的情况显然,
关于其他的情况,因为1最小,1必须在两端中的任意一个,(然后发现可以递推下去,(
复杂度 O ( n ) O(n) O(n)
正解code
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;
int a[maxn];
int an[maxn], cnt[maxn];
inline void init(int n) {
for(int i = 0; i <= n; ++i) {
an[i] = 0;
cnt[i] = 0;
}
}
int main() {
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
int T;
cin >> T;
while(T--) {
int n;
cin >> n;
init(n);
for(int i = 1; i <= n; ++i) {
cin >> a[i];
cnt[a[i]]++;
}
bool f = 0;
for(int i = 1; i <= n; ++i) {
if(!cnt[i]) {
f = 1;
break;
}
}
if(f) an[1] = 0;
else an[1] = 1;
if(cnt[1]) an[n] = 1;
if(!cnt[1]) {
for(int i = 1; i <= n; ++i) {
cout << 0;
}
cout << endl;
continue;
}
int l = 1, r = n;
int idx = 1;
for(int i = n; i > 1; --i) {
an[i] = 1;
int nxt = n - i + 1;
if(--cnt[nxt] == 0 && (a[l] == nxt || a[r] == nxt) && cnt[nxt + 1]) {
if(a[l] == nxt) ++l;
if(a[r] == nxt) --r;
continue;
}
break;
}
for(int i = 1; i <= n; ++i) {
cout << an[i];
}
cout << endl;
}
return 0;
}