专栏文章

2025寒假专场11

题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miqbitux
此快照首次捕获于
2025/12/04 02:06
3 个月前
此快照最后确认于
2025/12/04 02:06
3 个月前
查看原文
入门,模拟
我们可以用建树的思想找入度即可, aabb强就让bb的入度加一, 最后如果只有一个人没有入度, 说明他就是最强的; 如果有多个说明无法确定;
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;
}

可以从 1,N1+N21,N_1 + N_2 出发,分别进行 BFSBFS ,找该图中以其为起点,最短路最长的点。之后把这两个点连起来,就是题目需要的答案。
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;
}
二维前缀和+二分。
枚举左上角的位置,二分满足条件的正方形的边长,时间复杂度为nmlognn*mlogn
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 条评论,欢迎与作者交流。

正在加载评论...