do_while_true

一言(ヒトコト)

「比赛题解」AtCoder Beginner Contest 204 A-E简要题解

A:判断一下给出的俩是一样的还是不一样的,分成两类输出。

B:对于每个 \(A_i\),答案加上 \(\max(A_i-10,0)\)

C:对于每个点 \(\mathcal{O}(n)\) dfs 一遍能到达的点有多少个,加起来即可。

D:dp,设 \(f_{i,j}\) 为考虑前 \(i\) 个,是否存在“分成的两组较大的大小为 \(j\) ”的方案,dp复杂度 \(\mathcal{O}(n^2T)\)

E:Dij,每次算距离的时候三分一下,三分的时候按照不下取整算实数来三分,因为如果下取整的话会出现平的一段导致不能三分。

详细题解和代码有空补。

A

#include<iostream>
#include<cstdio>
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T>
T& read(T& r) {
	r = 0; bool w = 0; char ch = getchar();
	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
	return r = w ? -r : r;
}
signed main() {
	int a, b;
	read(a); read(b);
	if(a == b) printf("%d\n", a);
	else printf("%d\n", 3 - a - b);
	return 0;
}

B

#include<iostream>
#include<cstdio>
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T>
T& read(T& r) {
	r = 0; bool w = 0; char ch = getchar();
	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
	return r = w ? -r : r;
}
const int N = 1010;
int n, a[N], sum;
signed main() {
	read(n);
	for(int i = 1; i <= n; ++i) read(a[i]), sum += Max(0, a[i] - 10);
	printf("%d\n", sum); 
	return 0;
}

C

#include<iostream>
#include<cstdio>
typedef long long ll;
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T>
T& read(T& r) {
	r = 0; bool w = 0; char ch = getchar();
	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
	return r = w ? -r : r;
}
const int N = 2010;
int n, m, ent, head[N];
struct Edge {
	int next, to;
}e[N << 1];
inline void add(int x, int y) {
	e[++ent].to = y; e[ent].next = head[x]; head[x] = ent;
}
ll cnt, ans;
bool vis[N];
void dfs(int x) {
	if(vis[x]) return ;
	vis[x] = 1; ++cnt;
	for(int i = head[x]; i; i = e[i].next) dfs(e[i].to);
}
signed main() {
	read(n); read(m);
	for(int i = 1, u, v; i <= m; ++i) {
		read(u); read(v);
		add(u, v); //add(v, u);
	}
	for(int i = 1; i <= n; ++i) {
		for(int j = 1; j <= n; ++j) vis[j] = 0;
		cnt = 0;
		dfs(i);
		ans += cnt;
		}
	printf("%lld\n", ans);
	return 0;
}

D

#include<iostream>
#include<cstdio>
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T>
T& read(T& r) {
	r = 0; bool w = 0; char ch = getchar();
	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
	return r = w ? -r : r;
}
const int N = 110;
int n, a[N], s[N];
bool f[N][N*1000];
signed main() {
	read(n); 
	for(int i = 1; i <= n; ++i) read(a[i]), s[i] = s[i-1] + a[i];
	f[1][a[1]] = 1;
	for(int i = 1; i < n; ++i) {
		for(int j = 0; j <= s[i]; ++j)
			if(f[i][j])
				f[i+1][Max(j+a[i+1], s[i]-j)] = 1,
				f[i+1][Max(j, s[i]-j+a[i+1])] = 1;
	} int ans = 0;
	for(int i = 0; i <= s[n]; ++i)
		if(f[n][i]) {
			ans = i;
			break;
		}
	printf("%d\n", ans);
	return 0;
} 

貌似直接取根号就是最优的,赛时看了一眼觉得像对钩函数就莽了一手三分...

E

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#define int long long
typedef double ld;
typedef long long ll;
typedef std::pair<long long, int> pli;
#define mp std::make_pair
#define pp push_back
template <typename T> T Max(T x, T y) { return x > y ? x : y; }
template <typename T> T Min(T x, T y) { return x < y ? x : y; }
template <typename T>
T& read(T& r) {
	r = 0; bool w = 0; char ch = getchar();
	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
	return r = w ? -r : r;
}
const int N = 200010;
const ll INF = 0x7fffffffffffffff;
std::priority_queue<pli>q;
int n, m, head[N], ent;
ll dis[N];
bool vis[N];
struct Edge {
	int next, to, C, D;
}e[N << 1];
inline void add(int x, int y, int c, int d) {
	e[++ent].to = y;
	e[ent].C = c; e[ent].D = d;
	e[ent].next = head[x]; head[x] = ent;
}
inline ld f(int p, int x, int t) {
	return 1ll * t + 1.0 * e[p].D / (x + t + 1);
}
inline ll fl(int p, int x, int t) {
	return 1ll * t + std::floor(1.0 * e[p].D / (x + t + 1));
}
ll calc(int p, int x) {
	int l = 0, r = e[p].D;
	ll ans = INF;
	while(l <= r) {
		int y = (r - l) / 3, mid1 = l + y, mid2 = mid1 + y;
		ans = Min(ans, fl(p, x, l));
		ans = Min(ans, fl(p, x, r));
		ans = Min(ans, fl(p, x, mid1));
		ans = Min(ans, fl(p, x, mid2));
		if(f(p, x, mid1) >= f(p, x, mid2)) l = mid1+1;
		else r = mid2-1;
	}
	ans = Min(ans, fl(p, x, l)); ans = Min(ans, fl(p, x, r));
	ans = Min(ans, fl(p, x, l+1)); ans = Min(ans, fl(p, x, r+1));
	if(l) ans = Min(ans, fl(p, x, l-1));
	if(r) ans = Min(ans, fl(p, x, r-1));
	return ans + e[p].C;
}
signed main() {
	read(n); read(m);
	for(int i = 1, u, v, c, d; i <= m; ++i) {
		read(u); read(v); read(c); read(d);
		add(u, v, c, d); add(v, u, c, d);
	}
	for(int i = 2; i <= n; ++i) dis[i] = INF;
	q.push(mp(0, 1));
	while(!q.empty()) {
		int x = q.top().second; q.pop();
		if(vis[x]) continue;
		vis[x] = 1;
		for(int i = head[x]; i; i = e[i].next) {
			int v = e[i].to;
			ll cc = calc(i, dis[x]);
			if(dis[v] > dis[x] + cc) {
				dis[v] = dis[x] + cc;
				q.push(mp(-dis[v], v));
			}
		}
	}
	printf("%lld\n", dis[n] == INF ? -1 : dis[n]);
	return 0;
}
posted @ 2021-06-06 21:39  do_while_true  阅读(153)  评论(0编辑  收藏  举报