C
题意:给你一个网格,宽为W,高为H,然后输入N个坐标,对于(i = 1, 2,...,N),第i个坐标处填i,重复下面两种操作:
- 删除空行
- 删除空列
问最终每一个数字的位置在哪
方法: 排序去重+二分,由于(1≤H,W≤10^9),所以不能模拟来做,对于每一个数字只需要关心这个数字上面有一个非空行cntx,左边有几个非空列cnty,最终的位置就是(cntx + 1, cnty + 1)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int h, w, n;
vector<pair<int, int>> p;
vector<int> x, y;
int find(int x, vector<int> &v){
int l = 0, r = (int) v.size() - 1;
while(l < r){
int mid = l + r + 1 >> 1;
if(v[mid] <= x) l = mid;
else r = mid - 1;
}
if(v[l] <= x) return l + 1;
return 0;
}
int main(){
cin >> h >> w >> n;
for(int i = 0; i < n; i ++){
int a, b;
cin >> a >> b;
p.push_back({a, b});
x.push_back(a);
y.push_back(b);
}
sort(x.begin(), x.end());
sort(y.begin(), y.end());
x.resize(unique(x.begin(), x.end()) - x.begin());
y.resize(unique(y.begin(), y.end()) - y.begin());
for(int i = 0; i < n; i ++){
int cntx = find(p[i].first - 1, x), cnty = find(p[i].second - 1, y);
cout << cntx + 1 << ' ' << cnty + 1 << endl;
}
}
D
题意:给你一个树,打印从1出发把所有顶点访问一遍再回到1的递归过程,注意再访问过程中优先选择序号小的顶点
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N = 2e5 + 10;
int n;
vector<int> h[N];
vector<int> ans;
void dfs(int u, int pre){
for(int i = 0; i < h[u].size(); i ++){
int j = h[u][i];
if(j != pre){
ans.push_back(j);
dfs(j, u);
ans.push_back(u);
}
}
if(u == 1) return;
}
int main(){
cin >> n;
for(int i = 0; i < n - 1; i ++){
int a, b;
cin >> a >> b;
h[a].push_back(b);
h[b].push_back(a);
}
for(int i = 1; i < N; i ++) sort(h[i].begin(), h[i].end());
ans.push_back(1);
dfs(1, -1);
for(auto t : ans) cout << t << ' ';
}