Codeforces Round 886 (Div. 4)F~H

Codeforces Round 886 (Div. 4)F~H

F. We Were Both Children(枚举)

题意

有一堆青蛙,每次会跳ai步,最多跳到n,然后想知道在1~n里面,哪个点青蛙落地的次数最多

思路

先给ai相同的青蛙计数一下,map<int,int>w,表示有w[i]个青蛙的步数都是ai

然后枚举所有不同ai下,会在在1~n里,哪里落地,用cnt[]来计数,计数的时候注意权值w

看哪个点cnt最大就行

代码

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
vector<long long>ans;
map<int, int>vis, w, cnt;
vector<int>a;
void solve() {
	w.clear();
	vis.clear();
	cnt.clear();
	int n; cin >> n;
	a.clear(); a.resize(n + 1);
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		w[a[i]]++;
	}
	int res = 0;
	for (int i = 1; i <= n; i++) {
		if (vis[a[i]])continue;
		vis[a[i]]++;
		for (int k = 1; a[i] * k <= n; k++) {
			cnt[a[i] * k] += w[a[i]];
			res = max(res, cnt[a[i] * k]);
		}
	}
	ans.push_back(res);
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int _; _ = 1;
	cin >> _;
	while (_--)	solve();
	for (auto x : ans)cout << x << endl;
	return 0;
}
// 1 2 3 4 5

// 1 1 1 1 1
// 1 2 1 2 1
// 1 2 2 2 1
// 1 2 2 3 1
// 1 2 2 3 2

G. The Morning Star(数学)

题意

给一堆点,取两个点要在同一条直线上(有四条直线,不分方向)

思路

如果点a和点b在同一条直线上,他们的坐标有什么关系?

xa,ya,xb,yb

xa==xb || ya=yb(此时形成的线要么平行于x轴,要么垂直于x轴)

斜的,斜率为1或者-1
yb-ya == xb-xa

xa+ya == xb+yb

代码

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
vector<long long>ans;
void solve() {
	map<int, int>x, y, xy1, xy2;
	set<int>sx, sy, sxy1, sxy2;
	int n; cin >> n;
	for (int i = 1, a, b; i <= n; i++) {
		cin >> a >> b;
		x[a]++;
		y[b]++;
		xy1[a + b]++;
		xy2[a - b]++;
		sx.insert(a);
		sy.insert(b);
		sxy1.insert(a + b);
		sxy2.insert(a - b);
	}
	long long res = 0;
	for (auto num : sx) {
		res += x[num] * (x[num] - 1);
	}
	for (auto num : sy) {
		res += y[num] * (y[num] - 1);
	}
	for (auto num : sxy1) {
		res += xy1[num] * (xy1[num] - 1);
	}	
	for (auto num : sxy2) {
		res += xy2[num] * (xy2[num] - 1);
	}

	ans.push_back(res);
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int _; _ = 1;
	cin >> _;
	while (_--)	solve();
	for (auto x : ans)cout << x << endl;
	return 0;
}
/*
	星和指南针在同一条线上
	如果点a和点b在同一条直线上,他们的坐标有什么关系?
	xa,ya,xb,yb

	xa==xb || ya=yb

	斜的,斜率为1或者-1
	yb-ya == xb-xa

	xa+ya == xb+yb

	yb-ya/xb-xa = 1/-1
*/

H. The Third Letter(带权并查集)

题意

给一堆条件,a,b,d说明b在a前面d米(d是负的话就是a后面|d|米)

思路

带权并查集

定义dis[i]表示节点i到它的父节点的距离(不是根节点)

  • find

    int find(int x) {
    if (par[x] == x)return x;
    else {
    int parX = find(par[x]);

    ​ dis[x] += dis[par[x]];

    ​ par[x] = parX;

    ​ return par[x];

    ​ }

    }

  • merge

    void merge(int x, int y, int val) {
    int parX = find(x);
    int parY = find(y);
    //if (parX == parY)return;
    par[parY] = parX;
    dis[parY] = dis[x] - val - dis[y];
    }

边并查集边看看有没有矛盾就行

代码

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
vector<long long>ans;
const int N = 2e5 + 5;
int par[N], dis[N];

int find(int x) {
	if (par[x] == x)return x;
	else {
		int parX = find(par[x]);

		dis[x] += dis[par[x]];

		par[x] = parX;
		return par[x];
	}
}

void merge(int x, int y, int val) {
	int parX = find(x);
	int parY = find(y);
	//if (parX == parY)return;
	par[parY] = parX;
	dis[parY] = -dis[y] - val + dis[x];
}

void solve() {
	int n, m; cin >> n >> m;
	memset(dis, 0, sizeof(dis));
	for (int i = 1; i <= n; i++) {
		par[i] = i;
	}
	bool flag = false;
	for (int i = 0, a, b, d; i < m; i++) {
		cin >> a >> b >> d;
		if (flag)continue;
		if (find(a) != find(b)) {
			merge(a, b, d);
		}
		else {
			if (dis[a] - dis[b] != d) {
				flag = true;
			}
		}
	}
	if (flag)cout << "NO" << endl;
	else cout << "YES" << endl;
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	int _; _ = 1;
	cin >> _;
	while (_--)	solve();
	for (auto x : ans)cout << x << endl;
	return 0;
}
posted @ 2025-04-27 19:15  zombieee  阅读(14)  评论(0)    收藏  举报