VP Educational Codeforces Round 12


A. Buses Between Cities

题意:A站每a分钟一趟车,ta分钟到BB站每b分钟一趟车,tb分钟到A,从上午五点开始发车,一直到23:99最后一趟。给出你的坐车时间,求能遇到多少车。

模拟题。把时间都换算成分钟,那么枚举B车站发出的车,只要到站时间大于发车时间,就能遇见。

点击查看代码
void solve() {
	int a, ta, b, tb;
	std::cin >> a >> ta >> b >> tb;
	int n = 24 * 60;
	std::string s;
	std::cin >> s;
	int l = ((s[0] - '0') * 10 + s[1] - '0') * 60 + (s[3] - '0') * 10 + s[4] - '0';
	int r = l + ta;
	int ans = 0;
	for (int i = 5 * 60; i < n && i < r; i += b) {
		if (i + tb > l) {
			++ ans;
		}
	}   

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

B. Shopping

也是模拟,每次在一个数组找一个数插到最前面。

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

    int ans = 0;
    for (int i = 0; i < n; ++ i) {
    	for (int j = 0; j < m; ++ j) {
    		int x;
    		std::cin >> x;
    		int p = std::find(a.begin(), a.end(), x) - a.begin();
    		ans += p + 1;
    		while (p) {
    			std::swap(a[p], a[p - 1]);
    			-- p;
    		}
    	}
    }

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

C. Simple Strings

题意:修改最少的字符,使得字符串任意两个相邻字符都不相同。

如果我们从前往后做,遇到一个字符和前面的相同,我们应该改当前这个,因为改了前面的可能后面还和这个相同,还要多改一次。

点击查看代码
void solve() {
	std::string s;
	std::cin >> s;
	int n = s.size();
	for (int i = 1; i < n; ++ i) {
		if (s[i] == s[i - 1]) {
			int x = 0;
			while (x == s[i - 1] - 'a' || (i + 1 < n && x == s[i + 1] - 'a')) {
				x = (x + 1) % 26;
			}

			s[i] = x + 'a';
		}
	}    

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

D. Simple Subset

题意:给你一个数组,选尽可能多少数使得每个数两两互质。

发现除了1之外,奇数和偶数只能选一个,那么有1选1,然后看能不能选两个互质的数。

点击查看代码
const int N = 2e6 + 5;

int st[N];
std::vector<int> primes;
void init(int n) {
	for (int i = 2; i <= n; ++ i) {
		if (!st[i]) {
			primes.push_back(i);
		}

		for (auto & p : primes) {
			if (p * i > n) {
				break;
			}

			st[i * p] = 1;
			if (i % p == 0) {
				break;
			}
		}
	}
}

void solve() {
	init(2e6);
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::vector<int> ans1, ans2;
    for (int i = 0; i < n; ++ i) {
    	if (a[i] == 1) {
    		ans1.push_back(1);
    	}
    }

    bool flag = false;
    for (int i = 0; i < n && !flag; ++ i) {
    	for (int j = i + 1; j < n; ++ j) {
    		if (a[i] != 1 && a[j] != 1 && !st[a[i] + 1] && !st[a[j] + 1] && !st[a[i] + a[j]]) {
    			ans1.push_back(a[i]);
    			ans1.push_back(a[j]);
    			flag = true;
    			break;
    		}
    	}
    }

    if (!flag) {
    	for (int i = 0; i < n; ++ i) {
    		if (a[i] != 1 && !st[a[i] + 1]) {
    			ans1.push_back(a[i]);
    			break;
    		}
    	}
    }

    flag = false;
    for (int i = 0; i < n && !flag; ++ i) {
    	for (int j = i + 1; j < n; ++ j) {
    		if (!st[a[i] + a[j]]) {
    			ans2.push_back(a[i]);
    			ans2.push_back(a[j]);
    			flag = true;
    			break;
    		}
    	}
    }

    auto ans = ans1.size() > ans2.size() ? ans1 : ans2;
    if (ans.empty()) {
    	ans.push_back(a[0]);
    }

    std::cout << ans.size() << "\n";
    for (auto & x : ans) {
    	std::cout << x << " ";
    }

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

E. Beautiful Subarrays

题意:给你一个数组,求有多少子数组的异或和大于等于k

把前缀异或和插入字典树,然后每次按位查询sumi,分k这一位讨论,如果k这一位是1,那么只能找一个和suni异或1的路走,否则所有和suni异或为1的位置都累加答案。最后如果有异或和跟k相同的也加上。

点击查看代码
const int N = 1e6 + 6;

int trie[N * 30][2];
int node_cnt[N * 30];
struct TrieWith01 {
	int idx;
	int creat() {
		memset(trie[idx], 0, sizeof trie[idx]);
		node_cnt[idx] = 0;
		return idx ++ ;
	}

	TrieWith01() {
		idx = 0;
		creat();
	}

	void insert(int x) {
		int p = 0;
		for (int i = 29; i >= 0; -- i) {
			int s = x >> i & 1;
			if (!trie[p][s]) {
				trie[p][s] = creat();
			}

			p = trie[p][s];
			++ node_cnt[p];
		}
	}

	int xor_max(int x) {
		int p = 0;
		int res = 0;
		for (int i = 29; i >= 0; -- i) {
			int s = x >> i & 1;
			if (trie[p][!s]) {
				res += 1 << i;
				p = trie[p][!s];
			} else {
				p = trie[p][s];
			}
		}

		return res;
	}

	int query_geq(int x, int k) {
		int p = 0;
		int res = 0;
		for (int i = 29; i >= 0; -- i) {
			int a = x >> i & 1, b = k >> i & 1;
			if (b == 1) {
				p = trie[p][a ^ 1];
			} else {
				res += node_cnt[trie[p][a ^ 1]];
				p = trie[p][a];
			}

			if (p == 0) {
				break;
			}
		}

		if (p != 0) {
			res += node_cnt[p];
		}

		return res;
	}
};

void solve() {
    int n, k;
    std::cin >> n >> k;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::vector<int> sum(n + 1);
    for (int i = 0; i < n; ++ i) {
    	sum[i + 1] = sum[i] ^ a[i];
    }

    TrieWith01 tr;
    i64 ans = 0;
    tr.insert(0);
    for (int i = 1; i <= n; ++ i) {
    	ans += tr.query_geq(sum[i], k);
    	tr.insert(sum[i]);
    }

    std::cout << ans << "\n";
}
posted @   maburb  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示