K-Bag
K-Bag
https://ac.nowcoder.com/acm/contest/5671/K
题目大题:K—Bag:数组是由若干个长度为k的全排列组成的,然后在开头和结尾都可以删去位置连续的若干个元素。
最后要你判断是否是K-Bag
我们定义一种边(u, v);
若u=1 或v=n+1,则要求a[u],a[u+1],..,a[v-1]都是由不同的数字组成的
反之,我们要求 v-u == k, 并且要求a[u],a[u+1],..,a[v-1]恰好是一个全排列
至于为什么要这样定义。仔细想想就好了,每个边其实都代表下标[u,v)之间其实都是不悖于条件的,要么是完整的一个全排列,要么可能是被删去了一部分的全排列。
最后我们判断是否可以由1到达n+1, 若可以则输出YES,反之NO。
注意实现的细节。对于u=1 或 v=n+1, 我们可以特判,由于数字可能会很大,我们可以用set
unordered_set<int> se;
for(int i; i <= n; i++) {
if(a[i] > k) break;
if(se.find(a[i]) != se.end()) break;
add(1, i+1);
se.insert(a[i]);
}
se.clear();
for(int j = n; j >= 1; j--) {
if(a[i] > k) break;
if(se.find(a[j]) != se.end()) break;
add(j, n+1);
se.insert(a[j]);
} 然后对于另外一种边,我们可以用滑动窗口,至于为什么终点要多加一。自然是为了能让图连上啦。
vi数组用于判断是否出现。当然我们也可以发现只有n<=k的时侯才会出现这种边
int l = 1, cnt = 0;
if(k <= n)
for(int i = 1; i <= n; i++) {
if(a[i] > k) break;
if(vi[a[i]]) {
while(l < i && a[l] != a[i]) vi[a[l++]] = 0, cnt--;
if(l < i) l++;
if(cnt == k) add(l, i+1);
}
else {
cnt++;
vi[a[i]] = 1;
if(cnt == k) add(l, i+1);
}
}然后我们就可以开开心心的用bfs来判断是否可以到达n+1。
我的渣渣代码。
注意初始化!!!
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const double Pi = acos(-1);
namespace {
template <typename T> inline void read(T &x) {
x = 0; T f = 1;char s = getchar();
for(; !isdigit(s); s = getchar()) if(s == '-') f = -1;
for(; isdigit(s); s = getchar()) x = (x << 3) + (x << 1) + (s ^ 48);
x *= f;
}
}
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define _for(n,m,i) for (register int i = (n); i < (m); ++i)
#define _rep(n,m,i) for (register int i = (n); i <= (m); ++i)
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
#define lowbit(x) x & (-x)
#define pii pair<int,int>
#define fi first
#define se second
vector<int> v[500005];
bool vis[500005];
queue<int> q;
int p, n, a[500005];
void add(int l, int r) {
v[l].push_back(r);
}
bool dij() {
while(!q.empty()) q.pop();
q.push(1);
while (!q.empty()) {
p = q.front();
q.pop();
if(vis[n+1]) break;
if(vis[p]) continue;
vis[p] = 1;
for(auto it : v[p]) {
if(!vis[it])
q.push(it);
}
}
return vis[n+1] == 1;
}
bool vi[500005];
void init() {
int k; read(n); read(k);
_rep(1, n, i) read(a[i]), vis[i] = 0, v[i].clear(), vi[i] = 0;
v[n+1].clear(); vis[n+1] = 0;
unordered_set<int> se;
for(int i; i <= n; i++) {
if(a[i] > k) break;
if(se.find(a[i]) != se.end()) break;
add(1, i+1);
se.insert(a[i]);
}
se.clear();
for(int j = n; j >= 1; j--) {
if(a[j] > k) break;
if(se.find(a[j]) != se.end()) break;
add(j, n+1);
se.insert(a[j]);
}
se.clear();
int l = 1, cnt = 0;
if(k <= n)
for(int i = 1; i <= n; i++) {
if(a[i] > k) break;
if(vi[a[i]]) {
while(l < i && a[l] != a[i]) vi[a[l++]] = 0, cnt--;
if(l < i) l++;
if(cnt == k) add(l, i+1);
}
else {
cnt++;
vi[a[i]] = 1;
if(cnt == k) add(l, i+1);
}
}
}
int main() {
int t; read(t);
while(t--) {
init();
if(dij()) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
科大讯飞公司氛围 425人发布