AtCoder Beginner Contest 250 赛时记录

赛时发现 G 和 Ex 是原题而且自己都做过,直接贺了过来/kx

F 因为是算几只知道做法不是很会写。

rk23 赢麻了/kx,大概是最高名次了/kx

A - Adjacent Squares

简单特判。

signed main() {
	int H = read(), W = read();
	int R = read(), C = read();
	int ans = 0;
	ans += (R > 1);
	ans += (C > 1);
	ans += (R < H);
	ans += (C < W);
	cout << ans << "\n";
	return 0;
}

B - Enlarged Checker Board

简单模拟。

int f[1010][1010];
signed main() {
	int n = read(), a = read(), b = read();
	for(int i = 1; i <= n; ++i) 
		for(int j = 1; j <= n; ++j) 
			for(int l = 1; l <= a; ++l) 
				for(int r = 1; r <= b; ++r) 
					if((i + j) & 1) f[(i - 1) * a + l][(j - 1) * b + r] = 1;
	for(int i = 1; i <= n * a; ++i) {
		for(int j = 1; j <= n * b; ++j) 
			cout << (f[i][j] == 1 ? '#' : '.');
		puts("");
	}
	return 0;
}

C - Adjacent Swaps

数组的简单应用。

signed main() {
	int n = read(), Q = read();
	vector<int> a(n + 2), pre(n + 2);
	for(int i = 1; i <= n; ++i) a[i] = i, pre[i] = i;
	for(int i = 1; i <= Q; ++i) {
		int x = read(), u, v;
		if(pre[x] == n) {
			u = pre[x], v = pre[x] - 1;
		} else {
			u = pre[x], v = pre[x] + 1;
		}
		swap(a[u], a[v]);
		pre[a[u]] = u, pre[a[v]] = v;
	}
	for(int i = 1; i <= n; ++i) cout << a[i] << " "; puts("");
	return 0;
}

D - 250-like Number

一开始被题意坑了,以为 \(q\) 可以不是素数。

考虑暴力枚举素数。

因为 \(n \le 10^{18}\) 且 \(p < q\),所以 \(p < 10^5\)。

对于 \(q\) 的话只需要枚举 \(10^6\) 内的素数即可。

然后线筛一下 \(10^6\) 以内的所有素数暴力枚举就好了。

反正跑起来挺快的,复杂度大概是 \(10^5\) 带个 \(\log\) 这种级别。

int n, ans = 0;
int prim[MAXN], Cnt = 0;
bool vis[MAXN];
void Init(int M) {
	for(int i = 2; i <= M; ++i) {
		if(!vis[i]) prim[++Cnt] = i;
		for(int j = 1; j <= Cnt && i * prim[j] <= M; ++j) {
			vis[i * prim[j]] = true;
			if(i % prim[j] == 0) break;
		}
	}
}
void Print(__int128 x){
	if(x > 9) Print(x / 10);
	putchar(x % 10 + '0');
}
signed main() {
	Init(1000000); n = read();
	for(int i = 1; i <= Cnt; ++i) {
		int p = prim[i];
		for(int k = i + 1; k <= Cnt; ++k) {
			int j = prim[k];
			__int128 x = (__int128)p * j * j * j, y = n;
			if(x > y) break;
			ans ++;
		}
	}
	cout << ans << "\n";
	return 0;
}

E - Prefix Equality

一眼题。

考虑处理出某个数在另一个数组第一次出现的位置。

可以先离散化。

以 \(a\) 数组为例,处理出 \(a\) 数组的每一项在 \(b\) 数组中第一次出现的位置,然后建立线段树。

对于每次查询 \(x,y\),就是查询 \(a\) 数组的前 \(x\) 项中是不是所有元素都在 \(b\) 的前 \(y\) 项中出现,即判断 \(1 \sim x\) 中的最大值是不是 \(\le y\)。

然后对 \(b\) 也类似处理一下即可。

int n, Q;
int a[MAXN], b[MAXN];
int date[MAXN << 1], Cnt = 0, top = 0;
int vis[MAXN << 1], fir[MAXN << 1];
int Vis[MAXN << 1], Fir[MAXN << 1];

struct Seg {
#define lson i << 1
#define rson i << 1 | 1
	int Max[MAXN << 2];
	void Push_up(int i) { Max[i] = max(Max[lson], Max[rson]); }
	void Build(int i, int l, int r, int k) {
		if(l == r) { Max[i] = k ? Vis[l] : vis[l]; return ;}
		int mid = (l + r) >> 1;
		Build(lson, l, mid, k), Build(rson, mid + 1, r, k);
		Push_up(i);
	}
	int Query(int i, int l, int r, int L, int R) {
		if(L <= l && r <= R) return Max[i];
		int mid = (l + r) >> 1, ans = 0;
		if(mid >= L) ans = max(ans, Query(lson, l, mid, L, R));
		if(mid < R) ans = max(ans, Query(rson, mid + 1, r, L, R));
		return ans;
	}
}seg[2];

signed main() {
	n = read();
	for(int i = 1; i <= n; ++i) a[i] = read();
	for(int i = 1; i <= n; ++i) b[i] = read();
	for(int i = 1; i <= n; ++i) date[++top] = a[i], date[++top] = b[i];
	sort(date + 1, date + top + 1);
	Cnt = unique(date + 1, date + top + 1) - date - 1;
	for(int i = 1; i <= n; ++i) a[i] = lower_bound(date + 1, date + Cnt + 1, a[i]) - date;
	for(int i = 1; i <= n; ++i) b[i] = lower_bound(date + 1, date + Cnt + 1, b[i]) - date;
	for(int i = 1; i <= Cnt; ++i) fir[i] = n + 1, Fir[i] = n + 1;
	for(int i = n; i >= 1; --i) fir[b[i]] = i, Fir[a[i]] = i;
	for(int i = n; i >= 1; --i) vis[i] = fir[a[i]], Vis[i] = Fir[b[i]];
//	for(int i = 1; i <= n; ++i) cout << vis[i] << " "; puts("");
	Q = read();
	seg[0].Build(1, 1, n, 0);
	seg[1].Build(1, 1, n, 1);
	for(int i = 1; i <= Q; ++i) {
		int x = read(), y = read();
		int res1 = seg[0].Query(1, 1, n, 1, x);
		int res2 = seg[1].Query(1, 1, n, 1, y);
//		cout << x << " " << y << "\n";
		if(res1 <= y && res2 <= x) puts("Yes");
		else puts("No");
	}
	return 0;
}

F - One Fourth

计算几何题/px

考虑固定一个点,然后找到面积是最接近总面积 \(\frac{1}{4}\) 和 \(\frac{3}{4}\) 的地方,然后类似于双指针同时顺时针或者逆时针移动这些点即可,对所有结果取一个最优值。

G - Stonks

原题:CF865D

好像是简单反悔贪心。

就是从前向后扫,拿一个小根堆维护我们可能在哪些天买(具体天数不需要,只需要价格

如果发现当前这个值 \(p_i\) 大于堆顶 \(p_j\),那么我们可以在第 \(j\) 天买入第 \(i\) 天卖出,因此有一个 \(p_i - p_j\) 的贡献。然后我们把堆顶元素弹出,加入 \(p_i\) 即可。

如果后面有 \(p_k > p_i\),那么同样操作时会得到 \(p_k - p_i\) 的贡献,两次的贡献和相当于 \(p_k - p_j\),因此这么反悔贪心是对的。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n, ans = 0;
priority_queue<int, vector<int>, greater<int> > q;
signed main()
{
	cin >> n;
	for(int i = 1, x; i <= n; ++i) {
		cin >> x;
		if(!q.empty() && q.top() < x) ans += x - q.top(), q.pop(), q.push(x);
		q.push(x);
	}
	printf("%lld\n", ans);
	return 0;
}

Ex - Trespassing Takahashi

原题:CF1253F

和原题唯一的区别就是最后的判断。

可以去看我在洛谷写的题解:link。

这里还有一个在博客园的链接:link

/*
思路极其鬼畜:
1、最短路
2、生成树
3、倍增+LCA
4、查询 
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
//#include<time.h>
#define LL long long
#define int long long
#define orz cout<<"lkp AK IOI!"<<endl

using namespace std;
const int MAXN = 4e5+5;
const int MAXM = 6e5+5;
const int INF = 1e9+7;
const int mod = 1e9+7;

struct edge{
	int from, to, w, nxt;
}e[MAXM << 2], E[MAXM], E2[MAXM << 1];
int head[MAXN], num_edge = 0;
int Head[MAXN], Num_edge = 0;

struct node{
	int bh, val;
	bool operator < (const node &b) const { return val > b.val; }
};

int n, m, k, Q, cnt;
int dis[MAXN], fa[MAXN], f[MAXN][22], dep[MAXN], maxm[MAXN][22];
bool vis[MAXN];
priority_queue<node> q;

int read(){
	int s = 0, f = 0;
	char ch = getchar();
	while(!isdigit(ch))  f |= (ch == '-'), ch = getchar();
	while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
	return f ? -s : s;
}

bool cmp(edge x, edge y){ return x.w < y.w; }
void add_edge(int from, int to, int w){ e[++num_edge] = (edge){from, to, w, head[from]}, head[from] = num_edge; }
void Add_edge(int from, int to, int w){ E2[++Num_edge] = (edge){from, to, w, Head[from]}, Head[from] = Num_edge; }
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }

void dij(){
	memset(dis, 0x3f, sizeof dis);
	dis[0] = 0;
	q.push((node){0, 0});
	while(!q.empty()){
		node u = q.top(); q.pop();
		if(vis[u.bh]) continue;
		vis[u.bh] = true;
		for(int i = head[u.bh]; i; i = e[i].nxt){
			int v = e[i].to;
			if(dis[v] > dis[u.bh] + e[i].w){
				dis[v] = dis[u.bh] + e[i].w;
				if(!vis[v]) q.push((node){v, dis[v]});
			}
		}
	}
}

void kruskal(){
	for(int i = 1; i <= n; ++i) fa[i] = i;//重置父亲 
	for(int i = 1; i <= m; ++i){
		int uf = find(E[i].from), vf = find(E[i].to);
		if(uf != vf){
			fa[vf] = uf;
			Add_edge(E[i].from, E[i].to, E[i].w), Add_edge(E[i].to, E[i].from, E[i].w);//建出最小生成树来 
			cnt++;
			if(cnt == n - 1) return ;//如果建了n - 1条边,就结束 
		}
	}
}

void dfs(int u, int fa){//dfs预处理lca 
	f[u][0] = fa;
	for(int i = Head[u]; i; i = E2[i].nxt){
		int v = E2[i].to;
		if(v == fa) continue;
		dep[v] = dep[u] + 1;
		maxm[v][0] = E2[i].w;
		dfs(v, u);
	}
}

void init(){//预处理lca 
	for(int i = 1; i <= 20; ++i)
		for(int j = 1; j <= n; ++j)
			f[j][i] = f[f[j][i - 1]][i - 1],
			maxm[j][i] = max(maxm[j][i - 1], maxm[f[j][i - 1]][i - 1]);
}

int get_max(int x, int y){
	int ans = 0;
	if(dep[x] < dep[y]) swap(x, y);
	for(int i = 20; i >= 0; --i){
		if(dep[f[x][i]] < dep[y]) continue;
		ans = max(ans, maxm[x][i]);
		x = f[x][i];
	}
	if(x == y) return ans;
	for(int i = 20; i >= 0; --i){
		if(f[x][i] == f[y][i]) continue;
		ans = max(ans, max(maxm[x][i], maxm[y][i]));
		x = f[x][i], y = f[y][i];
	}
	ans = max(ans, max(maxm[x][0], maxm[y][0]));
	return ans;
}

signed main() {
	n = read(), m = read(), k = read();
	for(int i = 1, u, v, w; i <= m; ++i){
		u = read(), v = read(), w = read();
		add_edge(u, v, w), add_edge(v, u, w);
		E[i].from = u, E[i].to = v, E[i].w = w;
	}
	for(int i = 1; i <= k; ++i) add_edge(0, i, 0), add_edge(i, 0, 0);    
	dij();
	for(int i = 1; i <= m; ++i) E[i].w += dis[E[i].from] + dis[E[i].to];
	sort(E + 1, E + m + 1, cmp); 
	kruskal();	dep[1] = 1;	dfs(1, -1);	init();	Q = read();
	for(int i = 1, u, v, t; i <= Q; ++i){
		u = read(), v = read(), t = read();
		int res = get_max(u, v);
		if(res <= t) puts("Yes");
		else puts("No");
	}
	return 0;
}
posted @ 2022-05-09 08:18  Suzt_ilymtics  阅读(238)  评论(1)    收藏  举报