寒假第一场补题
C、兢兢业业之移
题意:给定一个\(n\times n\)的\(01\)矩阵,其中有\(\frac{n^2}{4}\)个\(1\),其余为\(0\),求如何将所有\(1\)移到左上角的一个\(\frac{n}{2}\times\frac{n}{2}\)的正方形区域中。
思路:对于每一个左上角的\(0\),用\(bfs\)找到最佳的\(1\)和最短路径,移动过去。
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\)的区间个数(贡献)
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;
}