腾个时间把代码贴一下
1.第一题: 无需实际建树,sort之后,进行二分查找即可,主要是到达叶节点后需要判断是否退出,否则会多一个L或者R
int main() { vector<int>nums; int temp; while (cin >> temp){ nums.emplace_back(temp); } int target = nums.back(); nums.pop_back(); // nums = {1,2,3,4,5,6,7}; // int target = 8; std::sort(nums.begin(), nums.end()); int n = nums.size(); int depth = 0; auto p = n + 1; while (p){ depth++; p >>= 1; } if(target > nums.back()){ cout << "S" + string(depth-2,'R') + "N"; return 0; } else if(target < nums.front()){ cout << "S" + string(depth-2,'L') + "N"; return 0; } int l = 0; int r = n; int mid = 0; int d = 0; string ans = "S"; while (l < r){ mid = l + ((r-l)/2); if(nums[mid] == target){ ans.push_back('Y'); cout << ans << endl; return 0; } // 到达叶节点深度,进行判断 if(d == depth - 2){ break; } if(nums[mid] < target){ ans.push_back('R'); l = mid + 1; } else{ ans.push_back('L'); r = mid; } d++; } ans.push_back('N'); cout << ans << endl; return 0; }
2.第二题: 构造一个struct,其包含(int)总得分,(int)连续得分,(string)失分情况和(int)id.之后写一个cmp进行排序即可]
class player{ public: int total; int lianxu; string loss; int id; player() = default; player(int t,int l,string&& lo,int i): total(t),lianxu(l),loss(lo),id(i){}; }; int main() { int n,m; cin >> n >> m; vector<string>arr; vector<player>players; for(int j = 0; j < n; j++){ string temp; cin >> temp; int total = std::count(temp.begin(), temp.end(),'1'); int cnt = 0; int lianxu = 0; string loss; for(int i = 0; i < temp.size(); i++){ if(temp[i] == '1'){ cnt++; lianxu = max(lianxu,cnt); } else{ loss.push_back(i + '0'); cnt = 0; } } players.emplace_back(total,lianxu,std::move(loss),j); } auto cmp = [&](const player& a,const player& b){ if(a.total == b.total){ if(a.lianxu == b.lianxu){ if(a.loss == b.loss){ return a.id < b.id; } return a.loss > b.loss; } return a.lianxu > b.lianxu; } return a.total > b.total; }; std::sort(players.begin(), players.end(),cmp); for(int i = 0; i < players.size(); i++){ cout << players[i].id + 1; if(i != players.size() -1 ){ cout << " "; } } return 0; }
3.第三题.
读题可知: 这个有向图中的每个节点的出度都是1,并且edges[i] != i [关键条件]
那么,对于并查集的每个连通域来说,这个连通域内最多有一个环,最少有一个环
那么对于一个连通域,我们可以先任选一个点作为出发点,使用快慢指针,快慢指针相遇的位置肯定在环内.
之后从相遇处再绕着走一圈回到相遇处,并将遍历到的节点记录下来,这就是环.
H的计算方式就是 H = 环的长度 - (并查集的大小-环的长度)
int main() { int n; cin >> n; vector<int>edges(n); for(int & edge : edges){ int temp; cin >> temp; edge = temp; } vector<int>root(n,-1); vector<int>weight(n,1); vector<int>start; function<int(int )> find = [&](int x){ if(root[x] == -1){ return x; } return root[x] = find(root[x]); }; auto to_union = [&](int x,int y){ auto px = find(x); auto py = find(y); if(px == py){ start.emplace_back(px); } else if(weight[px] > weight[py]){ root[py] = px; weight[px] += weight[py]; } else{ root[px] = py; weight[py] += weight[px]; } }; for(int i = 0; i < n; i++){ to_union(i,edges[i]); } int ans = INT_MIN; vector<int>vec; // y快指针,x慢指针 for(auto x:start){ auto y = edges[x]; while (x != y){ x = edges[x]; y = edges[edges[y]]; } vector<int>temp = {x}; y = edges[y]; while (x != y){ temp.emplace_back(y); y = edges[y]; } int H = (int)temp.size() - (weight[find(x)] - (int)temp.size()); if(H > ans){ ans = H; vec = temp; } else if(H == ans){ auto k1 = *std::max_element(vec.begin(), vec.end()); auto k2 = *std::max_element(temp.begin(), temp.end()); if(k2 > k1){ vec = temp; } } } rotate(vec.begin(), min_element(vec.begin(),vec.end()),vec.end()); for(int i = 0; i < vec.size(); i++){ cout << vec[i]; if(i != vec.size() - 1){ cout << " "; } } return 0; }