牛客寒假第一场补题
寒假第一场补题
C、兢兢业业之移
题意:给定一个\(n\times n\)的\(01\)矩阵,其中有\(\frac{n^2}{4}\)个\(1\),其余为\(0\),求如何将所有\(1\)移到左上角的一个\(\frac{n}{2}\times\frac{n}{2}\)的正方形区域中。
思路:对于每一个左上角的\(0\),用\(bfs\)找到最佳的\(1\)和最短路径,移动过去。
时间复杂度:\(O(n^4)\)
void solve()
{
int n;
cin >> n;
vector<string> g(n);
vector<vector<bool>> vis(n,vector<bool>(n,false));
vector<array<int,4>> ans;
for(int i = 0 ; i < n ; i ++) cin >> g[i];
auto bfs = [&](int sx,int sy){
queue<PII> q;
vector<vector<PII>> pre(n,vector<PII>(n));
vector<vector<int>> d(n,vector<int>(n,-1));
d[sx][sy] = 0;
q.push({sx,sy});
while(q.size()){
auto [x,y] = q.front();
q.pop();
if(g[x][y] == '1'){
swap(g[x][y],g[sx][sy]);
while(x != sx || y != sy){
auto [prex,prey] = pre[x][y];
ans.push_back({prex,prey,x,y});
x = prex, y = prey;
}
return;
}
for(int i = 0 ; i < 4 ; i ++){
int nx = x + dx[i], ny = y + dy[i];
if(nx < 0 || ny < 0 || nx >= n || ny >= n) continue;
if(d[nx][ny] != -1 || vis[nx][ny]) continue;
d[nx][ny] = d[x][y] + 1;
pre[nx][ny] = {x,y};
q.push({nx,ny});
}
}
};
for(int i = 0 ; i < n / 2 ; i ++){
for(int j = 0 ; j < n / 2 ; j ++){
if(g[i][j] == '0')
bfs(i,j);
vis[i][j] = true;
}
}
cout << ans.size() << endl;
for(auto [a,b,c,d] : ans)
cout << a + 1 << " " << b + 1 << " " << c + 1 << " " << d + 1 << endl;
// for(int i = 0 ; i < n ; i ++) cout << g[i] << endl;
}
F、双生双宿之探
题意:给定一个长度为\(n\)的数组,求有多少个连续区间构成双生数组(区间内只有两个数,且数量相等)
思路:
1、双生数组只能有两个值\(\Rightarrow\)找到所有最长的连续区间,且只有两个数\(\Rightarrow\)用双指针
2、双生数组中需要两个数数量相同\(\Rightarrow\)一个数记为\(1\),另一个数记为\(-1\),求前缀和后,重复出现的\(sum\)即为贡献\(\Rightarrow\)前缀和求和为\(0\)的区间个数(贡献)
时间复杂度:\(O(n\log n)\)
void solve()
{
int n;
int ans = 0;
cin >> n;
vector<int> a(n+1);
for(int i = 1 ; i <= n ; i ++) cin >> a[i];
int l = 1, r = 0;
set<int> st;
auto get = [&](int l,int r){
// cout << l << " " << r << endl;
vector<int> sum(n+1,0);
int f = a[l];
for(int i = l; i <= r ; i ++){
if(a[i] == f) sum[i] = 1;
else sum[i] = -1;
sum[i] += sum[i-1];
}
map<int,int> cnt;
cnt[0]++;
for(int i = l ; i <= r ; i ++){
ans += cnt[sum[i]];
cnt[sum[i]] ++;
}
};
while(l<=n&&r<=n){
r++;
st.insert(a[r]);
if(st.size() == 1) continue;
else if(st.size() == 3){
get(l,r-1);
// cout << l << " " << r - 1 << endl;
st.clear();
st.insert(a[r]);
st.insert(a[r-1]);
l = r - 1;
while(a[l-1] == a[l]) l --;
}
}
cout << ans << endl;
}

浙公网安备 33010602011771号