Educational Codeforces Round 55 (Rated for Div. 2) Solution
A. Vasya and Book
Solved.
三种方式取$Min$
#include <bits/stdc++.h>
using namespace std; #define ll long long
#define INF 0x3f3f3f3f3f3f3f3f
int t;
ll n, x, y, d; ll calc(ll x)
{
return x % d == ? x / d : x / d + ;
} int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%lld%lld%lld%lld", &n, &x, &y, &d);
ll res = INF;
if ((abs(y - x)) % d == ) res = min(res, (abs(y - x) / d));
if ((y - ) % d == ) res = min(res, calc(x) + (y - ) / d);
if ((n - y) % d == ) res = min(res, calc(n - x) + (n - y) / d);
if (res == INF) res = -;
printf("%lld\n", res);
}
return ;
}
B. Vova and Trophies
Solved.
合并相同种类,再判断是否有单独的S使得替换掉它合并后得到更优解
#include <bits/stdc++.h>
using namespace std; #define N 100010
#define pii pair <int, int>
int n, m;
char s[N];
pii a[N]; int main()
{
while (scanf("%d", &n) != EOF)
{
scanf("%s", s + );
int tot = s[] == 'G', m = , tmp = ;
for (int i = ; i <= n; ++i)
{
tot += s[i] == 'G';
if (s[i] != s[i - ])
{
a[++m] = pii(tmp, s[i] == 'G');
tmp = ;
}
++tmp;
}
a[++m] = pii(tmp, s[n] != 'G');
int res = ;
for (int i = ; i <= m; ++i)
{
if (a[i].second == )
res = max(res, min(tot, a[i].first + ));
else if (i != && i != m && a[i].first == )
res = max(res, min(tot, a[i - ].first + + a[i + ].first));
}
printf("%d\n", res);
}
return ;
}
C. Multi-Subject Competition
Solved.
题意:
有一个多学科竞赛,一名队员只会一门学科
派出去的队伍对于每个要参加的学科其参加的人数要相等
并且每个队员对于其会的那门学科有一个技能值
求如何派出队伍参加学科使得队伍中所有队员的技能值总和最大。
思路:
枚举要参加的学科派出的队员数,网上枚举,不符合条件的学科消除影响,每名队员只会遍历一次
时间复杂度$O(n)$
#include <bits/stdc++.h>
using namespace std; #define N 100010
int n, m;
vector <int> v[N];
int tot[N];
queue <int> q; int main()
{
while (scanf("%d%d", &n, &m) != EOF)
{
for (int i = ; i <= m; ++i) v[i].clear();
memset(tot, , sizeof tot);
while (!q.empty()) q.pop();
for (int i = , s, r; i <= n; ++i)
{
scanf("%d%d", &s, &r);
v[s].push_back(r);
}
for (int i = ; i <= m; ++i) sort(v[i].rbegin(), v[i].rend());
for (int i = ; i <= m; ++i) q.push(i);
int res = , tmp = ;
for (int i = ; ; ++i)
{
if (q.empty()) break;
for (int j = , len = q.size(); j <= len; ++j)
{
int top = q.front(); q.pop();
tmp -= tot[top];
if (v[top].size() < i)
continue;
tot[top] += v[top][i - ];
if (tot[top] <= ) continue;
tmp += tot[top];
q.push(top);
}
res = max(res, tmp);
}
printf("%d\n", res);
}
return ;
}
D. Maximum Diameter Graph
Solved.
题意:
给出一个n,和每个点最大的度数,构造一棵树,使得每个点的度数不超过最大度数,并且直径最长
思路:
如果所有点的度数之和小于$2 * (n - 1)$ 那么就不可以构造
否则将所有度数$>= 2的点放到直径上,再两边添加一个度为1的点(如果有)$
$剩下的点就连到这条直径上还有度数剩余的点上$
n给的好小,好怀疑自己的做法,当时。
#include <bits/stdc++.h>
using namespace std; #define N 510
int n, a[N];
vector <int> l, r; int main()
{
while (scanf("%d", &n) != EOF)
{
int sum = ;
l.clear(), r.clear();
for (int i = ; i <= n; ++i)
{
scanf("%d", a + i);
sum += a[i];
if (a[i] > ) l.push_back(i);
else r.push_back(i);
}
if (sum < * (n - )) puts("NO");
else
{
if (!r.empty()) l.insert(l.begin(), r.end()[-]), r.pop_back();
if (!r.empty()) l.push_back(r.end()[-]), r.pop_back();
printf("YES %d\n", (int)l.size() - );
printf("%d\n", n - );
for (int i = , len = l.size(); i < len; ++i) printf("%d %d\n", l[i], l[i - ]), --a[l[i]], --a[l[i- ]];
for (int i = , j = , len1 = l.size(), len2 = r.size(); i < len2; ++i)
{
while (a[l[j]] == ) ++j;
--a[l[j]];
printf("%d %d\n", r[i], l[j]);
}
}
}
return ;
}
E. Increasing Frequency
Solved.
题意:
给出一个n个数,可以选取一段$[l, r],$ 使得区间内所有数都$+k$
求最多进行一次这样的操作,使得最后$a_i == c$的个数最多
求这个最多的个数
思路:
显然一个区间的贡献这个区间内相同数字最大的个数加上区间外c的个数,然后这样区间枚举就是$O(n^2)$
我们可以考虑,枚举$a_i$ 即要把哪些数字变成$c$
那么这时候,所有不是$c也不是a_i 的数字就没有用$ 不妨把它们单独拿出来考虑(类似于虚树思想)
假设$L[i], R[i] 表i左边的c的个数 和 i 右边的c的个数$
那么我假设序列中有$x个a(a 为枚举的a_i)$
$L[1], R[1], ... L[x], R[x]$
我们$需要找一个以后 x, y 使得 R[y] + (y - x + 1) + L[x] 最大$
$那么可以枚举x ,然后即找一个最大的 (y - x + 1) + R[y]$
这个可以用线段树维护。
发现常数项是递增的,建树的时候就可以给它,每次更新的时候,相当于后面的每一个都减一
#include <bits/stdc++.h>
using namespace std; #define N 500010
int n, c, a[N], dpl[N], dpr[N];
vector <int> v[N]; namespace SEG
{
int Max[N << ], lazy[N << ];
void pushup(int id) { Max[id] = max(Max[id << ], Max[id << | ]); }
void build(int now, int id, int l, int r)
{
Max[id] = lazy[id] = ;
if (l == r)
{
Max[id] = l + dpr[v[now][l - ]];
return;
}
int mid = (l + r) >> ;
build(now, id << , l, mid);
build(now, id << | , mid + , r);
pushup(id);
}
void pushdown(int id)
{
if (!lazy[id]) return;
lazy[id << ] += lazy[id];
Max[id << ] += lazy[id];
lazy[id << | ] += lazy[id];
Max[id << | ] += lazy[id];
lazy[id] = ;
}
void update(int id, int l, int r, int ql, int qr)
{
if (l >= ql && r <= qr)
{
--Max[id];
--lazy[id];
return;
}
int mid = (l + r) >> ;
pushdown(id);
if (ql <= mid) update(id << , l, mid, ql, qr);
if (qr > mid) update(id << | , mid + , r, ql, qr);
pushup(id);
}
int query(int id, int l, int r, int ql, int qr)
{
if (l >= ql && r <= qr) return Max[id];
int mid = (l + r) >> ;
pushdown(id);
int res = ;
if (ql <= mid) res = max(res, query(id << , l, mid, ql, qr));
if (qr > mid) res = max(res, query(id << | , mid + , r, ql, qr));
return res;
}
} void init()
{
for (int i = ; i <= ; ++i) v[i].clear();
} int main()
{
while (scanf("%d%d", &n, &c) != EOF)
{
init();
for (int i = ; i <= n; ++i) scanf("%d", a + i), v[a[i]].push_back(i);
int tmp = ;
for (int i = ; i <= n; ++i)
{
dpl[i] = tmp;
tmp += a[i] == c;
}
tmp = ;
for (int i = n; i >= ; --i)
{
dpr[i] = tmp;
tmp += a[i] == c;
}
int res = ;
for (int i = ; i <= ; ++i) if (v[i].size())
{
int len = v[i].size();
SEG::build(i, , , len);
for (int j = ; j < len; ++j)
{
res = max(res, dpl[v[i][j]] + SEG::query(, , len, j + , len));
SEG::update(, , len, j + , len);
}
}
printf("%d\n", res);
}
return ;
}
F. Speed Dial
Upsolved.
题意:
给出一串电话号码,以及需要拨打的次数,有k个快捷键可以快速拨出一串号码,该号码可不在给出的电话号码中
求最少的按键次数(快捷键不算一次按键)
思路:
在$Trie树上DP$
$dp[x][rem][fa] 表示到第x个节点,剩余rem次快捷键使用,上一次使用快捷键的节点为fa$
$dp2[x][rem][fa][i] 前面含义相同,i 表示第i个子节点$
$dp[x][rem][fa] = min(dp[x][rem][fa], dp[x][rem - 1][x])$
$dp2[x][rem][fa][i] = min(dp2[x][rem][fa][i], dp2[x][rem - j][fa][i + 1] + dp[x[i]][j][fa])$
$dp[x][rem][fa] = min(dp[x][rem][fa], dp2[x][rem][fa][0] + cnt * len)$
#include <bits/stdc++.h>
using namespace std; #define INF 0x3f3f3f3f
#define N 510
int n, k, m;
struct TRIE
{
int cnt, deep;
int son[];
void init()
{
cnt = ;
memset(son, -, sizeof son);
}
}a[N]; int pos; char s[N]; int tot;
void insert()
{
scanf("%s%d", s, &tot);
int now = ;
for (int i = , len = strlen(s); i < len; ++i)
{
int to = s[i] - '';
if (a[now].son[to] == -)
{
a[now].son[to] = ++pos;
a[pos].init();
a[pos].deep = a[now].deep + ;
}
now = a[now].son[to];
}
a[now].cnt += tot;
} int dp[N][][N];
int dp2[N][][N][];
int DFS(int x, int rem, int fa)
{
if (dp[x][rem][fa] != -) return dp[x][rem][fa];
dp[x][rem][fa] = INF;
if (rem) dp[x][rem][fa] = DFS(x, rem - , x);
vector <int> G;
for (int i = ; i < ; ++i) if (a[x].son[i] != -)
G.push_back(a[x].son[i]);
dp2[x][rem][fa][G.size()] = ;
for (int i = (int)G.size() - ; i >= ; --i)
{
for (int j = ; j <= rem; ++j)
dp2[x][rem][fa][i] = min(dp2[x][rem][fa][i], dp2[x][rem - j][fa][i + ] + DFS(G[i], j, fa));
}
dp[x][rem][fa] = min(dp[x][rem][fa], dp2[x][rem][fa][] + a[x].cnt * (a[x].deep - a[fa].deep));
return dp[x][rem][fa];
} void init()
{
a[].init();
pos = ;
a[].deep = ;
} int main()
{
while (scanf("%d%d", &n, &k) != EOF)
{
init();
for (int i = ; i <= n; ++i) insert();
memset(dp, -, sizeof dp);
memset(dp2, 0x3f, sizeof dp2);
printf("%d\n", DFS(, k, ));
}
return ;
}
G. Petya and Graph
Unsolved.
Educational Codeforces Round 55 (Rated for Div. 2) Solution的更多相关文章
- Educational Codeforces Round 55 (Rated for Div. 2) C. Multi-Subject Competition 【vector 预处理优化】
传送门:http://codeforces.com/contest/1082/problem/C C. Multi-Subject Competition time limit per test 2 ...
- Educational Codeforces Round 55 (Rated for Div. 2) A/B/C/D
http://codeforces.com/contest/1082/problem/A WA数发,因为默认为x<y = = 分情况讨论,直达 or x->1->y or x-& ...
- Educational Codeforces Round 55 (Rated for Div. 2) B. Vova and Trophies 【贪心 】
传送门:http://codeforces.com/contest/1082/problem/B B. Vova and Trophies time limit per test 2 seconds ...
- Codeforces 1082 C. Multi-Subject Competition-有点意思 (Educational Codeforces Round 55 (Rated for Div. 2))
C. Multi-Subject Competition time limit per test 2 seconds memory limit per test 256 megabytes input ...
- Codeforces 1082 A. Vasya and Book-题意 (Educational Codeforces Round 55 (Rated for Div. 2))
A. Vasya and Book time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...
- Educational Codeforces Round 55 (Rated for Div. 2):E. Increasing Frequency
E. Increasing Frequency 题目链接:https://codeforces.com/contest/1082/problem/E 题意: 给出n个数以及一个c,现在可以对一个区间上 ...
- Educational Codeforces Round 55 (Rated for Div. 2):D. Maximum Diameter Graph
D. Maximum Diameter Graph 题目链接:https://codeforces.com/contest/1082/problem/D 题意: 给出n个点的最大入度数,要求添加边构成 ...
- Educational Codeforces Round 55 (Rated for Div. 2):C. Multi-Subject Competition
C. Multi-Subject Competition 题目链接:https://codeforces.com/contest/1082/problem/C 题意: 给出n个信息,每个信息包含专业编 ...
- Educational Codeforces Round 55 (Rated for Div. 2)E
题:https://codeforces.com/contest/1082/problem/E 题意:给出n个数和一个数c,只能操作一次将[L,R]之间的数+任意数,问最后该序列中能存在最多多少个c ...
随机推荐
- swift - UISwitch 的用法
具体代码如下,和oc的使用没有差别: 创建: let hswitch = UISwitch() /*创建开关,以及监听它值的改变,代码如下*/ //开关位置 hswitch.center = CGPo ...
- Python 使用正则表达式匹配URL网址
使用正则表达式匹配以 .com 或 .cn 为域名后缀的URL地址 In [1]: import re In [2]: str = "http://www.baidu.com/" ...
- Android 使用DatePicker以及TimePicker显示当前日期和时间
课程内容1.介绍DatePicker和TimePicker两种实现动态输入日期和事件的功能2.介绍DatePickerDialog和TimePickerDialog来年耕种实现动态输入日期和事件的对话 ...
- 实现类似printf这样的函数
来源:http://www.vimer.cn/2009/12/cc%E5%AE%9E%E7%8E%B0%E5%A4%9A%E5%8F%82%E6%95%B0%E5%87%BD%E6%95%B0%E7% ...
- 解决报错:scandir() has been disabled for security reasons
服务器环境: LNMP 在服务器部署代码时候.遇到了这个问题. 蛋疼啊! 2 解决办法: 打开phpinfo.php , 搜索: scandir 找到disabled_function,确认此函数未 ...
- JS-在线运行代码小工具
原理:window.open()方法,open一个新的空白页,然后把文本框中粘贴的代码通过DOM操作,写到新的代码页中, 再利用document.write的功能(写进去之前把其他的全部删掉,并且写进 ...
- Android ImageResizer:inSampleSize
import android.annotation.TargetApi; import android.content.Context; import android.content.res.Reso ...
- url-loader与file-loader
一开始用url-loader的时候,想着为什么npm run build的时候,不能将图片打包到build images的目录下,原来,没有自己看这样的说明: loader 后面 limit 字段代表 ...
- Python 中的线程-进程2
原文:https://www.cnblogs.com/i-honey/p/7823587.html Python中实现多线程需要使用到 threading 库,其中每一个 Thread类 的实例控制一 ...
- TDD中的单元测试写多少才够?
测试驱动开发(TDD)已经是耳熟能详的名词,既然是测试驱动,那么测试用例代码就要写在开发代码的前面.但是如何写测试用例?写多少测试用例才够?我想大家在实际的操作过程都会产生这样的疑问. 3月15日,我 ...