VP Educational Codeforces Round 15


Educational Codeforces Round 15

题意:求严格递增子数组的最长长度。

双指针经典题。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    int ans = 0;
    for (int i = 0; i < n; ++ i) {
    	int j = i;
    	while (j + 1 < n && a[j + 1] > a[j]) {
    		++ j;
    	}

    	ans = std::max(ans, j - i + 1);
    	i = j;
    }

    std::cout << ans << "\n";
}

B. Powers of Two

题意:求数组中有多少对的和是2的幂。

存每个数的个数,然后枚举2的幂统计。

点击查看代码
void solve() {
	int n;
	std::cin >> n;
	std::map<i64, int> mp;
	std::set<i64> s;
	for (int i = 0; i < n; ++ i) {
		i64 x;
		std::cin >> x;
		s.insert(x);
		++ mp[x];
	}    

	i64 ans1 = 0, ans2 = 0;
	for (i64 i = 1; i <= 30; ++ i) {
		for (auto & x : s) {
			if (!s.count((1ll << i) - x)) {
				continue;
			}
			if ((1ll << i) - x == x) {
				ans1 += (i64)mp[x] * (mp[x] - 1) / 2;
			} else {
				ans2 += (i64)mp[x] * mp[(1ll << i) - x];
			}
		}
	}

	std::cout << ans1 + ans2 / 2 << "\n";
}

C. Cellular Network

题意:有n个城市和n个电台在一个坐标轴上,求电台传播半径最小是多少可以让每个城市至少被一个电台覆盖。

二分长度,check里用差分写,找每个电台可以覆盖的最小坐标的城市和最大坐标的城市。

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<i64> a(n), b(m);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    for (int i = 0; i < m; ++ i) {
    	std::cin >> b[i];
    }

    auto check = [&](i64 x) -> bool {
    	std::vector<int> d(n + 2);
    	for (int i = 0; i < m; ++ i) {
    		int l = std::lower_bound(a.begin(), a.end(), b[i] - x) - a.begin() + 1;
    		int r = std::upper_bound(a.begin(), a.end(), b[i] + x) - a.begin();
    		if (l <= r) {
    			++ d[l];
    			-- d[r + 1];
    		}
    	}

    	for (int i = 1; i <= n; ++ i) {
    		d[i] += d[i - 1];
    		if (d[i] <= 0) {
    			return false;
    		}
    	}

    	return true;
    };

    i64 l = 0, r = 2e9;
    while (l < r) {
    	i64 mid = l + r >> 1ll;
    	if (check(mid)) {
    		r = mid;
    	} else {
    		l = mid + 1;
    	}
    }

    std::cout << l << "\n";
}

D. Road to Post Office

题意:你要走d公里,车子每公里用时a,且每走k公里需要维护t秒。步行没有限制,每公里用时b。求到达终点的最小时刻。

如果我们枚举车子走多少米,然后剩下的步行,会超时。但发现如果开车更优,那么我们应该一直开车,最后一段步行,或者直接一直开车。那么就可以分情况讨论,如果d<k,直接开车直达。发现我们看一直开车更优还是步行更优,注意步行前我们应该把能开车的距离用掉。

点击查看代码
void solve() {
    i64 d, k, a, b, t;
    std::cin >> d >> k >> a >> b >> t;
    if (d < k) {
    	std::cout << a * d << "\n";
    	return;
    }

    i64 ans = k * a + (d - k) * b;
	ans = std::min(ans, t * (d / k) + d * a);{
	ans = std::min(ans, t * (d / k - 1) + (d - d % k) * a + b * (d % k));}
	std::cout << ans << "\n";
}

E. Analysis of Pathes in Functional Graph

题意:有一个nn边的有向图,每个点都恰好有一条出边。求每个点走k的距离的路径总和和路径上边权最小值。

可以考虑倍增,预处理son[i][j],sum[i][j],min[i][j]表示从i2j距离到达的点、路径总和,路径最小边权。那么对于每个点就按照2的幂从大到小枚举跳。

点击查看代码
void solve() {
	int n;
	i64 k;
	std::cin >> n >> k;
	std::vector<int> f(n), w(n);
	for (int i = 0; i < n; ++ i) {
		std::cin >> f[i];
	}

	for (int i = 0; i < n; ++ i) {
		std::cin >> w[i];
	}

	const int inf = 2e9;
	const int lg = std::__lg(k) + 1;
	std::vector son(n, std::vector<int>(lg + 1));
	std::vector sum(n, std::vector<i64>(lg + 1));
	std::vector min(n, std::vector<i64>(lg + 1, inf));

	for (int i = 0; i < n; ++ i) {
		son[i][0] = f[i];
		sum[i][0] = w[i];
		min[i][0] = w[i];
	}	

	for (int j = 1; j <= lg; ++ j) {
		for (int i = 0; i < n; ++ i) {
			son[i][j] = son[son[i][j - 1]][j - 1];
			sum[i][j] = sum[i][j - 1] + sum[son[i][j - 1]][j - 1];
			min[i][j] = std::min(min[i][j - 1], min[son[i][j - 1]][j - 1]);
		}
	}

	for (int i = 0; i < n; ++ i) {
		i64 ans1 = 0, ans2 = inf;
		int u = i;
		for (i64 j = lg; j >= 0; -- j) {
			if (k >> j & 1) {
				ans1 += sum[u][j];
				ans2 = std::min(ans2, min[u][j]);
				u = son[u][j];
			}
		}

		std::cout << ans1 << " " << ans2 << "\n";
	}
}
posted @   maburb  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示