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 ...
随机推荐
- 服务端用例设计的思(tao)路!
服务端的测试简单来说就是除了前端以外的的测试. 总的来说可以分为以下两类: 1. WEB或者APP的提供业务逻辑的服务端接口测试 2. 数据库.缓存系统.中间件..jar包依赖.输入输 ...
- Linux环境下$开头的相关变量的含义
$0 这个程式的执行名字$n 这个程式的第n个参数值,n=1..9$* 这个程式的所有参数,此选项参数可超过9个.$# 这个程式的参数个数$$ 这个程式的PID(脚本运行的当前进程ID号)$! 执行上 ...
- MySQL性能优化(三)-- 索引
一.什么是索引及索引的特点 索引是一种数据结构 索引的特点:查找速度快,排好序,数据结构 索引的数据结构类型有:BTREE索引和HASH索引,下面展示的是BTREE索引. BTREE:balance ...
- Python 数据类型:字符串
一.字符串介绍 字符串是由单引号/双引号/三引号引起来的,由字母 .数字或符号等构成的一串字符 In [1]: name = "Tom" # 定义字符串 In [2]: type( ...
- PyQt4信号与槽
事件 事件(Events)是GUI程序中很重要的一部分.它由用户或系统产生.当我们调用程序的exec_()方法时,程序就会进入主循环中.主循环捕获事件并将它们发送给相应的对象进行处理.奇趣公司(Tro ...
- php之常量
前面的话 常量在javascript中并不存在,在php中却是与变量并列的重要内容.常量类似变量,但常量一旦被定义就无法更改或撤销定义.常量最主要的作用是可以避免重复定义,篡改变量值,提高代码可维护性 ...
- poj_3283 trie树
题目大意 将一副牌进行编号,四种花色分别标记为'C'.'D'.'H'.'S',数值标记为'A'.'1'.'2'.'3'.'4'.'5'.'6'.'7'.'8'.'9'.'10'.'J'.'Q'.'K' ...
- 【BZOJ3437】小P的牧场 斜率优化
[BZOJ3437]小P的牧场 Description 背景 小P是个特么喜欢玩MC的孩纸... 描述 小P在MC里有n个牧场,自西向东呈一字形排列(自西向东用1…n编号),于是他就烦恼了:为了控制这 ...
- 在linux下安装Avria(小红伞)
1.下载AntiVir PersonalEdition Classic for linux http://www.free-av.com/ 2.解压: tar zxvf antivir.tar.gz ...
- 有限制的最短路spfa+优先队列
poj1724 ROADS Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10751 Accepted: 3952 De ...