腾讯3.31 笔试AK C++题解
评价是都是常规mid,昨晚做美团笔试做的道心破碎
T3 并查集
使用并查集划分得到数个连通域,连通域的数量应为2.
仅建立一次连接就可以使得整个联通的连接数等于 第一个连通域内点数乘以第二个连通域内的点数.
class UnionFind{ private: vector<int>parents; vector<int>ranks; long long summary; public: unordered_map<int,int>mp; UnionFind(int max_size): parents(max_size), ranks(max_size){ for(int i=0;i<max_size;i++){ parents[i] = i; mp[i] = 1; } } int find(int x){ return x==parents[x] ? x : (find(parents[x])); } void to_union(int x1,int x2){ int f1 = find(x1); int f2 = find(x2); if(f1 == f2){ return; } summary -= mp[f1]*mp[f2]; if(ranks[f1] > ranks[f2]){ parents[f2] = f1; mp[f1] +=mp[f2]; mp.erase(f2); } else{ parents[f1] = f2; mp[f2] += mp[f1]; mp.erase(f1); if(ranks[f1] == ranks[f2]){ ranks[f2]++; } } } bool isConnected(int x,int y){ return find(x) == find(y); } }; int main() { int n,m; cin >> n >> m; int u,v; UnionFind uf(n); for(int i = 0; i < m; i++){ cin >> u >> v; uf.to_union(u - 1, v - 1); } if(uf.mp.size() > 2){ cout << 0 << endl; return 0; } vector<int>nums; for(const auto &p : uf.mp){ nums.emplace_back(p.second); } cout << nums[0] * nums[1] << endl; }
T4 前缀异或和 + 动态规划
这个题的数量级在400,感觉不用前缀和,暴力求异或和也能过.
int main() { long long n,k; cin >> n >> k; vector<long long >nums(n); long long val; for(int i = 0; i < n; i++){ cin >> val; nums[i] = val; } vector<long long>prefix(n,0); long long sum = 0; for(int i = 0; i < nums.size(); i++){ sum ^= nums[i]; prefix[i] = sum; } // [j-i]的前缀异或和 = prefix[j] ^ prefix[i] vector<vector<long long> >dp(k + 1,vector<long long>(n,0ll)); // dp[i][j] 表示 分了i段时,以下标 j 结尾的 最大和 // dp[i][j] = max(dp[i-1][m] + (prefix[j] ^ prefix[m]) ) m∈[0,j-1] for(int j = 0;j < dp[0].size();j++){ dp[1][j] = prefix[j]; } for(int i = 2 ; i < dp.size(); i++){ for(int j = i-1; j < dp[0].size(); j++){ long long cur = 0; for(int m = j-1; m >= 0; m--){ cur = max(cur,dp[i-1][m] + (prefix[j] ^ prefix[m]) ); } dp[i][j] = cur; } } cout << dp[k][n-1] << endl; }
T5 dfs
dfs + 回溯 LC79
int main() { int n,m; cin >> n >> m; vector<string>grid(n); for(int i = 0; i < n; i++){ string str; cin >> str; grid[i] = str; } string target = "tencent"; int cnt = 0; auto isValid = [&](int i,int j){ return i >=0 && i < grid.size() && j >= 0 && j < grid[0].size() ; }; function<void(int,int,int)> dfs = [&](int i,int j,int id)->void { if(!isValid(i,j) || grid[i][j] != target[id]){ return ; } if(id == target.size()-1){ cnt++; return; } dfs(i+1,j,id+1); // 下 dfs(i-1,j,id+1); // 上 dfs(i,j+1,id+1); // 右 dfs(i,j-1,id+1); // 左 }; for(int i = 0 ; i < grid.size(); i++){ for(int j = 0; j < grid[0].size(); j++){ dfs(i,j,0); } } cout << cnt << endl; }