Codeforces Round #591
Contest Info
[Practice Link](https://codeforces.com/contest/1240)
Solved | A | B | C | D | E | F |
---|---|---|---|---|---|---|
4/6 | O | O | O | O | - | - |
- O 在比赛中通过
- Ø 赛后通过
- ! 尝试了但是失败了
- - 没有尝试
Solutions
A. Save the Nature
题意:
有\(n\)个数\(p_i\)。
- 如果一个下标它是\(a\)的倍数,那么这个位置的价值就是\(a_i \cdot x\%\)
- 如果一个下标它是\(b\)的倍数,那么这个位置的价值就是\(a_i \cdot y\%\)
- 如果一个下标它是\(lcm(a, b)\)的倍数,那么这个位置的价值就是\(a_i \cdot (x + y)\%\)
现在可以给\(p_i\)重新排序,问排序最最少多少个前\(y\)个数,使得前\(y\)个数的价值和大于等于\(k\)。
思路:
二分答案,然后将大的贪心放在大的位置上。
代码:
view code
#include <bits/stdc++.h>
#define debug(...) { printf("# "); printf(__VA_ARGS__); puts(""); }
#define fi first
#define se second
#define endl "\n"
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long;
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; }
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }
inline void pt() { cout << endl; }
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << " "; pt(args...); }
template <class T> inline void pt(const T &s) { cout << s << "\n"; }
template <class T> inline void pt(const vector <T> &vec) { for (auto &it : vec) cout << it << " "; cout << endl; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
constexpr int N = 2e5 + 10;
int n, p[N], x, y, a, b; ll k;
bool check(ll mid) {
ll lcm = 1ll * a * b / gcd(a, b);
ll cnt[3] = {mid / a - mid / lcm, mid / b - mid / lcm, mid / lcm};
ll tot = 0;
for (int i = 1; i <= mid; ++i) {
if (cnt[2]) {
tot += 1ll * p[i] / 100 * (x + y);
--cnt[2];
} else if (cnt[1]) {
tot += 1ll * p[i] / 100 * y;
--cnt[1];
} else if (cnt[0]) {
tot += 1ll * p[i] / 100 * x;
--cnt[0];
} else break;
}
return tot >= k;
}
void run() {
cin >> n;
for (int i = 1; i <= n; ++i) cin >> p[i];
sort(p + 1, p + 1 + n, [&](int x, int y) { return x > y; });
cin >> x >> a >> y >> b >> k;
if (x > y) swap(x, y), swap(a, b);
int l = 1, r = n, res = -1;
while (r - l >= 0) {
int mid = (l + r) >> 1;
if (check(mid)) {
res = mid;
r = mid - 1;
} else
l = mid + 1;
}
pt(res);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cout << fixed << setprecision(20);
int _T; cin >> _T;
while (_T--) run();
return 0;
}
B. Sequence Sorting
题意:
给出一个序列\(a_i\),每次可以选择一种数,将这种数全丢到前面或者全丢到后面。
问最少操作几次,使得该序列变成非降序。
思路:
考虑最多保留多少种数。显然保留下来的肯定是非降序的数,并且是连续的。
那么直接扫一遍即可。
代码:
view code
#include <bits/stdc++.h>
#define debug(...) { printf("# "); printf(__VA_ARGS__); puts(""); }
#define fi first
#define se second
#define endl "\n"
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long;
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; }
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }
inline void pt() { cout << endl; }
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << " "; pt(args...); }
template <class T> inline void pt(const T &s) { cout << s << "\n"; }
template <class T> inline void pt(const vector <T> &vec) { for (auto &it : vec) cout << it << " "; cout << endl; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
constexpr int N = 3e5 + 10;
int n, a[N], l[N], r[N];
void run() {
cin >> n;
memset(l, 0x3f, sizeof (l[0]) * (n + 10));
memset(r, 0, sizeof (r[0]) * (n + 10));
for (int i = 1; i <= n; ++i) {
cin >> a[i];
chmin(l[a[i]], i);
chmax(r[a[i]], i);
}
int res = 1, tot = 0;
int lst = 0, sum = 0;
for (int i = 1; i <= n; ++i) if (r[i] != 0) {
++tot;
if (l[i] > lst) {
lst = r[i];
++sum;
chmax(res, sum);
} else {
lst = r[i];
sum = 1;
}
}
pt(tot - res);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cout << fixed << setprecision(20);
int _T; cin >> _T;
while (_T--) run();
return 0;
}
C. Paint the Tree
题意:
给出一棵树,给每个点涂上\(k\)种颜色,一种颜色最多涂给两个点,但是有无限种颜色可以涂。
一条边的价值是如果它两个端点共有至少一种颜色,那么它的价值为它的权值,否则为\(0\)。
现在问整棵树所有边的价值和最大是多少,在最优涂色方案下。
思路:
\(f[i][0]\)表示\(i\)的子树中并且\(i\)没有一种颜色可以涂的最大价值,\(f[i][1]\)表示\(i\)的子树中并且\(i\)还剩了至少一种颜色可以涂的最大价值。
那么一个\(u\),它最多选择\(k\)个\(f[v][1] + w\)进行转移,我们先假设全都选\(f[v][0]\)转移,然后维护一个堆,里面放的是\(f[v][1] + w - f[v][0]\),贪心选取前\(k\)大即可。
代码:
view code
#include <bits/stdc++.h>
#define debug(...) { printf("# "); printf(__VA_ARGS__); puts(""); }
#define fi first
#define se second
#define endl "\n"
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long;
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; }
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }
inline void pt() { cout << endl; }
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << " "; pt(args...); }
template <class T> inline void pt(const T &s) { cout << s << "\n"; }
template <class T> inline void pt(const vector <T> &vec) { for (auto &it : vec) cout << it << " "; cout << endl; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
constexpr int N = 5e5 + 10;
int n, k, fa[N]; ll f[N][2], g[N];
vector <vector<pII>> G;
void dfs(int u) {
f[u][0] = f[u][1] = 0;
for (auto &it : G[u]) {
int v = it.fi, w = it.se;
if (v == fa[u]) continue;
fa[v] = u;
dfs(v);
g[v] = f[v][1] + w - f[v][0];
f[u][0] += f[v][0];
f[u][1] += f[v][0];
}
vector <int> id;
for (auto &it : G[u]) if (it.fi != fa[u]) id.push_back(it.fi);
sort(id.begin(), id.end(), [&](int x, int y) { return g[x] > g[y]; });
for (int i = 0, sze = id.size(); i < k && i < sze; ++i) {
int v = id[i];
if (g[v] < 0) break;
if (i < k - 1) f[u][1] += g[v];
f[u][0] += g[v];
}
}
void run() {
cin >> n >> k;
G.clear(); G.resize(n + 1);
for (int i = 1, u, v, w; i < n; ++i) {
cin >> u >> v >> w;
G[u].emplace_back(v, w);
G[v].emplace_back(u, w);
}
fa[1] = 1;
dfs(1);
pt(max(f[1][0], f[1][1]));
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cout << fixed << setprecision(20);
int _T; cin >> _T;
while (_T--) run();
return 0;
}
D. Stack Exterminable Arrays
题意:
给出\(n\)个数,维护一个栈,将一个数列加到栈中,这么加:
- 如果栈空或者栈顶不等于当前数\(a_i\),那么将\(a_i\)加入到栈顶
- 如果栈顶的数等于当前数\(a_i\),那么栈顶弹出。
现在询问有多少连续子序列操作完后栈是空的。
思路:
我们考虑枚举每个连续子序列的右端点,统计有多少个左端点满足。
我们用\(S[i]\)表示前\(i\)个数的操作完后的栈序列。
那么当且仅当\(S[i] = S[j]\)的时候,\([i +1, j]\)这段序列操作完后栈是空的。
将\(S[i]\)哈希一下即可。
代码:
view code
#include <bits/stdc++.h>
#define debug(...) { printf("# "); printf(__VA_ARGS__); puts(""); }
#define fi first
#define se second
#define endl "\n"
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long;
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; }
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }
inline void pt() { cout << endl; }
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << " "; pt(args...); }
template <class T> inline void pt(const T &s) { cout << s << "\n"; }
template <class T> inline void pt(const vector <T> &vec) { for (auto &it : vec) cout << it << " "; cout << endl; }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
constexpr int N = 3e5 + 10;
//
struct Hash {
static ull base[N];
static void init() {
base[0] = 1;
for (int i = 1; i < N; ++i)
base[i] = base[i - 1] * 19260817;
}
ull a[N];
inline void work() { a[0] = 0; }
inline void add(int ch, int id) {
a[id] = a[id - 1] * 19260817 + ch;
}
}hs;
ull Hash::base[N] = {0};
map <ull, int> mp;
int n, a[N], sta[N];
void run() {
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
mp.clear();
mp[0] = 1; *sta = 0;
ll res = 0;
hs.work();
for (int i = 1; i <= n; ++i) {
if (*sta && sta[*sta] == a[i]) --*sta;
else sta[++*sta] = a[i], hs.add(a[i], *sta);
ull H = hs.a[*sta]; res += mp[H];
++mp[H];
}
pt(res);
}
int main() {
Hash::init();
ios::sync_with_stdio(false);
cin.tie(nullptr); cout.tie(nullptr);
cout << fixed << setprecision(20);
int _T; cin >> _T;
while (_T--) run();
return 0;
}
Codeforces Round #591的更多相关文章
- Codeforces Round #591 (Div. 2)
A. CME 题目链接:https://codeforces.com/contest/1241/problem/A 题意: 你有 N 根火柴 , 多少根火柴就可以组成多大的数(如 三根火柴可以表示 3 ...
- Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) C. Save the Nature【枚举二分答案】
https://codeforces.com/contest/1241/problem/C You are an environmental activist at heart but the rea ...
- Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) D. Sequence Sorting
链接: https://codeforces.com/contest/1241/problem/D 题意: You are given a sequence a1,a2,-,an, consistin ...
- Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) B. Strings Equalization
链接: https://codeforces.com/contest/1241/problem/B 题意: You are given two strings of equal length s an ...
- Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) C. Save the Nature
链接: https://codeforces.com/contest/1241/problem/C 题意: You are an environmental activist at heart but ...
- Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) A. CME
链接: https://codeforces.com/contest/1241/problem/A 题意: Let's denote correct match equation (we will d ...
- Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1)
Virtual participate 的,D题不会做,打了1:30就打不动了,过了ABCE. A - CME 题意:? 题解:? void test_case() { int n; scanf(&q ...
- Codeforces Round #591 (Div. 2, based on Technocup 2020 Elimination Round 1) 题解
A..B略 C 对当前的值排序,再二分答案,然后对于(i%x==0 && i%y==0)放入大的,再放其他的贪心解决即可. #include<iostream> #incl ...
- Codeforces Round #366 (Div. 2) ABC
Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...
随机推荐
- LINUX驱动笔记 目录
笔记参考了宋宝华老师的<Linux设备驱动开发详解:基于最新的Linux 4.0内核>以及韦东山老师的嵌入式驱动教程 笔记开发环境: 单板:第一章到第八章使用TINY4412-1611:第 ...
- 集合并卷积的三种求法(分治乘法,快速莫比乌斯变换(FMT),快速沃尔什变换(FWT))
也许更好的阅读体验 本文主要内容是对武汉市第二中学吕凯风同学的论文<集合幂级数的性质与应用及其快速算法>的理解 定义 集合幂级数 为了更方便的研究集合的卷积,引入集合幂级数的概念 集合幂级 ...
- css文字截断
通过css将文字进行截断,截断部分使用省略号代替 .impleName{ max-width: 100%; /*最大宽度为当前元素的100%*/ display: inline-block; whit ...
- flutter从入门到精通五
在flutter的世界里,一切都是Widget,图像,文本,布局模型等等,一切都是Widget flutter中,尽量将Widget放在MaterialApp.其封装了所需要的一些Widget,Mat ...
- CCF 2017-03-1 分蛋糕
CCF 2017-03-1 分蛋糕 题目 问题描述 小明今天生日,他有n块蛋糕要分给朋友们吃,这n块蛋糕(编号为1到n)的重量分别为a1, a2, -, an.小明想分给每个朋友至少重量为k的蛋糕.小 ...
- 在Linux上安装Zookeeper集群
xl_echo编辑整理,欢迎转载,转载请声明文章来源.欢迎添加echo微信(微信号:t2421499075)交流学习. 百战不败,依不自称常胜,百败不颓,依能奋力前行.——这才是真正的堪称强大!! - ...
- 关于/var/log/maillog 时间和系统时间不对应的问题 -- 我出现的是日志时间比系统时间慢12个小时
那么让我们来见证奇迹的时刻吧!! 首先你要看下/etc/localtime的软连接,到哪了 一般就是这块出问题了 检查这里就绝对不会错的 对比图 : 这种情况, 删除/etc/localtime : ...
- 2019最新Web前端经典面试试题(含答案)
1,阐述清楚浮动的几种方式(常见问题)(1)父级div定义 height原理:父级div手动定义height,就解决了父级div无法自动获取到高度的问题. 优点:简单.代码少.容易掌握 缺点:只适合高 ...
- Ubuntu 与 Debian 的关系
Debian 于 1993年8月16日 由一名美国普渡大学学生 Ian Murdock 首次发表. Debian 是由 GPL 和其他自由软件许可协议授权的自由软件组成的操作系统, 由 Debian ...
- MVC-Session
1.什么是Session? Session即会话,是指一个用户在一段时间内对某一个站点的一次访问. Session对象在.NET中对应HttpSessionState类,表示"会话状态& ...