专栏文章
2025寒假专场11
题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqbitux
- 此快照首次捕获于
- 2025/12/04 02:06 3 个月前
- 此快照最后确认于
- 2025/12/04 02:06 3 个月前
入门,模拟
我们可以用建树的思想找入度即可, 比强就让的入度加一, 最后如果只有一个人没有入度, 说明他就是最强的; 如果有多个说明无法确定;
CPP#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n,m;
bool st[N];
int main(){
cin >> n >> m;
for(int i = 1; i <= m; i++){
int a,b;
cin >> a >> b;
st[b] = true;
}
int ans = 0;
for(int i = 1; i <= n; i++){
if(!st[i]){
if(ans == 0) ans = i;
else {
cout << -1;
return 0;
}
}
}
cout << ans;
return 0;
}
入门,模拟
CPP#include<bits/stdc++.h>
using namespace std;
const int N = 100 + 10;
int n, m, idx;
int c[N];
set<int> s[N];
vector<int> v;
bool cmp(int a, int b) {
if (c[a] == c[b]) return a < b;
return c[a] < c[b];
}
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> c[i];
for (int j = 1; j <= c[i]; j++) {
int x;
cin >> x;
s[i].insert(x);
}
}
cin >> idx;
for (int i = 1; i <= n; i++) {
if (s[i].count(idx)) v.push_back(i);
}
if (v.empty()) {
cout << 0 << endl;
return 0;
}
sort(v.begin(), v.end(), cmp);
int minn = c[*v.begin()];
for (int i = 0; i < v.size(); i++) {
if (c[v[i]] == minn) m++;
else break;
}
cout << m << endl;
for (int i = 0; i < m; i++) {
cout << v[i] << " ";
}
return 0;
}
可以从 出发,分别进行 ,找该图中以其为起点,最短路最长的点。之后把这两个点连起来,就是题目需要的答案。
CPP#include<bits/stdc++.h>
using namespace std;
void solve(){
int n1, n2, m;
cin >> n1 >> n2 >> m;
vector<int> e[n1 + n2 + 2], vis(n1 + n2 + 2, 0), d(n1 + n2 + 2, 0);
for(int i = 1; i <= m; i++){
int u, v;
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
int m1 = 0, m2 = 0;
queue<int> q;
q.push(1); d[1] = 0; vis[1] = 1;
while(q.size()){
int cur = q.front(); q.pop();
for(auto y : e[cur]){
if( !vis[y] ){
q.push(y);
vis[y] = 1;
d[y] = d[cur] + 1;
m1 = max(m1, d[y]);
}
}
}
q.push(n1 + n2); d[n1 + n2] = 0; vis[n1 + n2] = 1;
while(q.size()){
int cur = q.front(); q.pop();
for(auto y : e[cur]){
if(!vis[y]){
q.push(y);
vis[y] = 1;
d[y] = d[cur] + 1;
m2 = max(m2, d[y]);
}
}
}
cout << m1 + m2 + 1 << '\n';
}
int main(){
solve();
return 0;
}
首先记录每个人买到的保险最多可以保护几代人。之后从族谱的根节点开始更新,记录当前这个人买的或者继承的族谱最多可以再保护几代人。
CPP#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
const int M = 2 * N;
int fa[N];
vector<int>g[M];
int n, m, col[N];
void dfs(int x, int f){
col[x] = max(col[x], col[f] - 1);
for(auto y: g[x]){
if(y == f) continue;
dfs(y, x);
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 2; i <= n; i++){
int x; scanf("%d", &x);
fa[i] = x;
g[i].push_back(x);
g[x].push_back(i);
}
for(int i = 1; i <= m; i++){
int x, y;
scanf("%d%d", &x, &y);
col[x] = max(col[x], y + 1);
}
dfs(1, 0);
int ans = 0;
for(int i = 1; i <= n; i++)
if(col[i])
ans++;
printf("%d\n", ans);
return 0;
}
二维前缀和+二分。
枚举左上角的位置,二分满足条件的正方形的边长,时间复杂度为
CPP#include<bits/stdc++.h>
using namespace std;
const int N = 3000 + 10;
int sum[N][N], a[N][N];
int n, m, k;
bool check(int x, int y, int len){
int nx = x + len - 1;
int ny = y + len - 1;
int res = sum[nx][ny] - sum[nx][y - 1] - sum[x - 1][ny] + sum[x - 1][y - 1];
return res == 0;
}
int main(){
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= k; i++){
int x, y;
scanf("%d%d", &x, &y);
a[x][y] = 1;
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j];
long long ans = 0;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= m; j++){
int l = 0, r = min(n - i + 1, m - j + 1);
int len;
while(l <= r){
int mid = (l + r) / 2;
if(check(i, j, mid)){
len = mid;
l = mid + 1;
}
else
r = mid - 1;
}
ans += 1ll * len;
}
}
printf("%lld\n", ans);
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...