Codeforces Round #466 (Div. 2) Solution
从这里开始
小结
这场比赛和同学一起打。本来应该是很开心的事情,结果留下好多遗憾。
第一个遗憾是没能在20分钟内消灭A、B题。然后分数就不是很可观。
我第一次交B题都20多分钟了。然后朋友们说我的贪心有锅,然后我就真信了。
于是我就重新写了个贪心交一发。好玩的是,考完我重新交了下B题之前的程序A了。
C、D题做得比较快,因为比较简单。(想吐槽一句。为什么cf div 2前4题只有普及组难度了?)
E题是最好玩的。读完题,写出了dp式子,我觉得会和按$c$分段有关,然后ZJC表示我在搞笑,我怎么又信了?
然后思路就被带偏了。然后写暴力dp打表找决策单调性,然而写挂了,样例都挂,然后就弃疗了。
比赛最后10分钟,红太阳QJX表示她A掉了E题,转移不是长度为1就是$c$。剩下的人全部在试图hack这个做法。(为什这个时候我就不信了qwq)
看到Doggu的一个朋友1小时A掉5道题,最后一题直接弃坑。我的内心是崩溃的。
主要还是A、B题做得太慢了吧。真正有意思的题目到后面都没时间思考。
综上所述,还是我太菜了。
-->
Codeforces 940A Points on the line
题目大意
定义一个可重集的距离是它中间最大的两个数之间的差,特殊地,只有一个元素的可重集的距离为0。
给定一个可重集,问最少删掉多少个数使得它的距离小于等于d。
排序后单调指针扫,或者直接开桶计数。
Code
/**
* Codeforces
* Problem#940A
* Accepted
* Time: 15ms
* Memory: 2000k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; int n, d;
int res;
int* ar; inline void init() {
scanf("%d%d", &n, &d);
ar = new int[(n + )];
for (int i = ; i <= n; i++)
scanf("%d", ar + i);
} inline void solve() {
sort (ar + , ar + n + );
int r = ;
res = n - ;
for (int i = ; i <= n; i++) {
while (r < n && ar[r + ] - ar[i] <= d) r++;
res = min(res, i + (n - r) - );
}
printf("%d", res);
} int main() {
init();
solve();
return ;
}
Problem A
Codeforces 940B Our Tanya is Crying Out Loud
题目大意
给定一个数$n$和$k$。你有两个操作可以进行
- 将$n$减去1,花费$a$。
- 当$n$是$k$的倍数的时候,将$n$除以$k$,花费$b$。
问将$n$变为1的最小花费
当 $k = 1$ 的时候特判。
当$n$为$k$的倍数的时候,比较直接除和直接减到$\frac{n}{k}$的花费,如果前者更优就除,否则直接减到1。
当$n$不为$k$的倍数的时候,直接减到$\left \lfloor\frac{n}{k} \right \rfloor k$。
考虑如果在 $ik$ 的决策不是减到 $i$ 或者直接除 $k$ 得到 $i$,那么考虑一定是做了若干次减法操作得到 $p$ 然后再除以 $k$ 得到 $x$。不难证明先除以 $k$ 得到 $l$,再做若干次减法操作得到 $x$ 不会更劣。
考虑这么做的正确性,唯一这么做的问题是会不会存在多减几次使答案更优的情况。
答案是不会的,因为先除可以避免使用多次的减法(除更优的情况下)。
举个例子来说明,将$k^{2} + k$变为1。
方案1:$k ^ {2} + k \rightarrow k + 1 \rightarrow k \rightarrow 1$
方案2:$k ^ {2} + k \rightarrow k^{2} \rightarrow k \rightarrow 1$
方案1使用了1次加法和2次除法,而方案二使用了$k$次加法和2次除法。
-->
Code
/**
* Codeforces
* Problem#940B
* Accepted
* Time: 30ms
* Memory: 2000k
*/
#include <bits/stdc++.h>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std; #define ll long long ll n, k, a, b, res = ; inline void init() {
scanf(Auto""Auto""Auto""Auto, &n, &k, &a, &b);
} inline void solve() {
if (k == ) {
res = (n - ) * a;
} else {
while (n != ) {
if (n < k) {
res += (n - ) * a;
break;
} else {
res += min((n % k) * a + b, (n - n / k) * a);
n /= k;
}
}
}
printf(Auto"\n", res);
} int main() {
init();
solve();
return ;
}
Problem B
Codeforces 940C Phone Numbers
题目大意
给定一个由小写字母组成且长度为$n$的字符串$s$,要求输出一个字符串$t$,满足:
- $t$中出现的字符在$s$中也出现过
- 它的长度为$k$
- $t$的字典序大于$s$
- 在满足上述条件的所有串中,是字典序最小的一个
题目保证存在解。
当$k > n$时,直接输出字符串$s$,再补上$s$中最小的字符。
否则找到$s$中从第$k$个字符往前找第一个不是最大的字符,把它变为略比它的字符。
然后后面的补最小的字符。
Code
/**
* Codeforces
* Problem#940C
* Accepted
* Time: 31ms
* Memory: 2100k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; int n, k;
int mi = , ma = ;
boolean exist[];
char str[]; inline void init() {
scanf("%d%d", &n, &k);
memset(exist, false, sizeof(exist));
scanf("%s", str + );
} inline void solve() {
for (int i = ; i <= n; i++)
exist[str[i] - 'a'] = true;
for (mi = ; !exist[mi]; mi++);
for (ma = ; !exist[ma]; ma--);
if (n < k) {
printf("%s", str + );
for (int i = n + ; i <= k; i++)
putchar(mi + 'a');
return;
}
int p;
for (p = k; p && str[p] == ma + 'a'; p--);
str[p]++;
while (!exist[str[p] - 'a'])
str[p]++;
for (p = p + ; p <= k; p++)
str[p] = mi + 'a';
str[k + ] = ;
puts(str + );
} int main() {
init();
solve();
return ;
}
Problem C
Codeforces 940D Alena And The Heater
题目大意
给定一个数组$a$,和一个01串$b$,$b$按照如下方式生成(请自行阅读英文)
请你找出一组合法的$l, r$,保证输入存在解。
发现生成方式比较特殊。
于是根据生成方式更新$l, r$即可。
Code
/**
* Codeforces
* Problem#940D
* Accepted
* Time: 31ms
* Memory: 2500k
*/
#include <bits/stdc++.h>
using namespace std; int n;
int a[];
char b[]; inline void init() {
scanf("%d", &n);
for (int i = ; i <= n; i++)
scanf("%d", a + i);
scanf("%s", b + );
} char sameNumber(int p) {
char x = b[p - ];
for (int i = ; i <= ; i++)
if (b[p - i] != x)
return '';
return x;
} int l = -1e9, r = 1e9; inline void solve() {
for (int i = ; i <= n; i++) {
char c = sameNumber(i);
if (c == '') continue;
if (c == b[i]) continue;
if (c == '') {
for (int j = ; j <= ; j++)
r = min(r, a[i - j] - );
} else {
for (int j = ; j <= ; j++)
l = max(l, a[i - j] + );
}
}
printf("%d %d", l, r);
} int main() {
init();
solve();
return ;
}
Problem D
Codeforces 940E Cashback
题目大意
给定一个长度为$n$的数组和常数$c$,要求你对它进行划分。划分长度为$k$一段的代价是其中所有除去前$\left \lfloor \frac{k}{c} \right \rfloor$小的数的和。定义一个划分的代价是划分的所有段的代价的和。
问最小的代价和。
一段代价可以表示为这一段的和减去前$\left \lfloor \frac{k}{c} \right \rfloor$小的数的和。
那么考虑两段连续的长度为$c$的合并到一起,这样会使得前2小的和变小。所以划分的最长的长度不会超过$2c - 1$
那么考虑长度在$c + 1$和$2c - 1$之间的段。我只需要留一个长度为$c$的段,把它和剩下的分开。这样看的话,划分的一段的长度不会超过$c$。
继续考虑长度小于$c$的段,它的代价直接就是它中间的元素的和。因此可以直接把它分成一些只有1个元素的段。
因此存在一种最优方案满足划分的每一段长度不是1就是$c$。
因此我只用维护连续$c$个元素的最小值,以及它们的和。
于是上单调队列。
时间复杂度$O(n)$。
Code
/**
* Codeforces
* Problem#940E
* Accepted
* Time: 31ms
* Memory: 3700k
*/
#include <bits/stdc++.h>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std; #define ll long long const int N = ; int n, c;
int st = , ed = ;
ll f[N];
int ar[N];
int que[N]; inline void init() {
scanf("%d%d", &n, &c);
for (int i = ; i <= n; i++)
scanf("%d", ar + i);
} inline void solve() { f[] = ;
ll sum = ;
for (int i = ; i <= n; i++) {
while (ed >= st && ar[que[ed]] >= ar[i]) ed--;
que[++ed] = i;
f[i] = f[i - ] + ar[i];
sum += ar[i];
while (ed >= st && que[st] <= i - c) st++;
if (i >= c)
sum -= ar[i - c], f[i] = min(f[i], f[i - c] + sum - ar[que[st]]);
} printf(Auto"\n", f[n]);
} int main() {
init();
solve();
return ;
}
Problem E
Codeforces 940F Machine Learning
题目大意
给定一个长度为$n$的数组,要求支持两个操作:
- 询问一个区间中所有数的出现次数组成的集合的mex。
- 修改一个位置上的数。
一个可重集合的mex是这个可重集合中最小的不存在的非负整数。
这种毒瘤题?我也不会做。那就直接莫队好了。
什么?要修改?那就带修莫队好了。
唯一的问题是如何求一个集合的mex?
考虑是出现次数,所以答案不会超过500(因为$C_{500}^{2}= \frac{500 \times 499}{2}>10^{5}$),超过500次的出现次数直接扔,查询操作暴力for。
时间复杂度$O\left(n^{\frac{5}{3}}\right)$
Code
/**
* Codeforces
* Problem#940F
* Accepted
* Time: 1872ms
* Memory: 11700k
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; #define pii pair<int, int>
#define fi first
#define sc second const int cs3 = , cs2 = ; typedef class Query {
public:
int l, r, t;
int id; Query(int l = , int r = , int t = , int id = ):l(l), r(r), t(t), id(id) { } boolean operator < (Query b) const {
if (l / cs3 != b.l / cs3) return l < b.l;
if (r / cs3 != b.r / cs3) return r < b.r;
return t < b.t;
}
}Query; int n, m;
int cm = , cq = , cd = ;
int* ar;
Query* qs;
pii *ops;
int cnt[];
int exist[];
int cover[cs2];
int *res;
map<int, int> mp; int alloc(int x) {
if (mp.count(x)) return mp[x];
return mp[x] = ++cd;
} inline void init() {
scanf("%d%d", &n, &m);
ar = new int[(n + )];
ops = new pii[(m + )];
qs = new Query[(m + )];
res = new int[(m + )];
for (int i = ; i <= n; i++)
scanf("%d", ar + i), ar[i] = alloc(ar[i]);
for (int i = , opt, l, r; i <= m; i++) {
scanf("%d%d%d", &opt, &l, &r);
if (opt == )
++cq, qs[cq] = Query(l, r, cm, cq);
else
r = alloc(r), ops[++cm] = pii(l, r);
}
exist[] = , cover[] = ;
} inline void update(int x, int sign) {
if (!exist[x] && sign == ) cover[x / cs2]++;
exist[x] += sign;
if (!exist[x] && sign == -)cover[x / cs2]--;
} inline void updatec(int p, int sign) {
int x = ar[p];
update(cnt[x], -);
cnt[x] += sign;
update(cnt[x], );
} inline void update(int op, int l, int r) {
int p = ops[op].fi;
if (l <= p && p <= r)
updatec(p, -);
swap(ar[p], ops[op].sc);
if (l <= p && p <= r)
updatec(p, );
} inline void solve() {
sort(qs + , qs + cq + );
int mdzzl = , mdzzr = , mdzzt = ;
for (int i = ; i <= cq; i++) {
while (mdzzr < qs[i].r) updatec(++mdzzr, );
while (mdzzr > qs[i].r) updatec(mdzzr--, -);
while (mdzzl < qs[i].l) updatec(mdzzl++, -);
while (mdzzl > qs[i].l) updatec(--mdzzl, );
while (mdzzt < qs[i].t) update(++mdzzt, mdzzl, mdzzr);
while (mdzzt > qs[i].t) update(mdzzt--, mdzzl, mdzzr); for (int j = ; j < cs2; j++) {
if (cover[j] < cs2) {
int k = j * cs2;
while (exist[k]) k++;
res[qs[i].id] = k;
break;
}
}
} for (int i = ; i <= cq; i++)
printf("%d\n", res[i]);
} int main() {
init();
solve();
return ;
}
Problem F
Codeforces Round #466 (Div. 2) Solution的更多相关文章
- Codeforces Round #466 (Div. 2) E. Cashback
Codeforces Round #466 (Div. 2) E. Cashback(dp + 贪心) 题意: 给一个长度为\(n\)的序列\(a_i\),给出一个整数\(c\) 定义序列中一段长度为 ...
- Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F
Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...
- Codeforces Round #466 (Div. 2) -A. Points on the line
2018-02-25 http://codeforces.com/contest/940/problem/A A. Points on the line time limit per test 1 s ...
- Codeforces Round #466 (Div. 2)
所有的题目都可以在CodeForces上查看 中间看起来有很多场比赛我没有写了 其实是因为有题目没改完 因为我不想改,所以就没有写了(大部分题目还是改完了的) 我还是觉得如果是打了的比赛就一场一场写比 ...
- 老年OIer的Python实践记—— Codeforces Round #555 (Div. 3) solution
对没错下面的代码全部是python 3(除了E的那个multiset) 题目链接:https://codeforces.com/contest/1157 A. Reachable Numbers 按位 ...
- Codeforces Round #545 (Div. 1) Solution
人生第一场Div. 1 结果因为想D想太久不晓得Floyd判环法.C不会拆点.E想了个奇奇怪怪的set+堆+一堆乱七八糟的标记的贼难写的做法滚粗了qwq靠手速上分qwqqq A. Skyscraper ...
- Codeforces Round 500 (Div 2) Solution
从这里开始 题目地址 瞎扯 Problem A Piles With Stones Problem B And Problem C Photo of The Sky Problem D Chemica ...
- Codeforces Round #466 (Div. 2) A. Points on the line[数轴上有n个点,问最少去掉多少个点才能使剩下的点的最大距离为不超过k。]
A. Points on the line time limit per test 1 second memory limit per test 256 megabytes input standar ...
- Codeforces Round #607 (Div. 1) Solution
从这里开始 比赛目录 我又不太会 div 1 A? 我菜爆了... Problem A Cut and Paste 暴力模拟一下. Code #include <bits/stdc++.h> ...
随机推荐
- Oracle 11g快速收集全库统计信息
环境:Oracle 11.2.0.4 采用并行的方式,快速收集全库统计信息,多用于跨版本升级之后,对全库的统计信息重新进行快速收集: --开启计时 set timing on --设置并行收集 exe ...
- httpServletResquire 和httpServletResponse
package com.bjsxt.servlet.request; import java.io.IOException;import javax.servlet.ServletException; ...
- 安装FusionInsight
1.在华为平台上下载整体客户端,不建议下载单个组件客户端,后期关联测试还是要装上的. 2.下载后需要将服务器上的客户端拷贝到本地.打开xShell,新建会话,登陆本地虚拟机上的Linux系统(19 ...
- c# 调试模式下Swaggerf附加接口参数
c# 调试模式下Swaggerf附加接口参数,如:每个接口Header中附加参数appId 1.新增过滤器: public class GlobalHttpHeaderFilter : IOperat ...
- Oracle数据库备份实验笔记[不完整,内容乱]
rman target / log=/orasoft/backup/${DATE}backup1.log <<EOFrun {allocate channel c1 device type ...
- uvm设计分析——tlm
tlm模块,用来在不同模块之间实现实时通信,主要基于两个定义在通信双方的port类来实现. 两个port之间,通过connect函数,来拿到双方的class指针,进而调用对方的function. 但是 ...
- html5-样式表的使用-初步
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- Nginx技术研究系列6-配置详解
前两篇文章介绍了Nginx反向代理和动态路由: Ngnix技术研究系列1-通过应用场景看Nginx的反向代理 Ngnix技术研究系列2-基于Redis实现动态路由 随着研究的深入,很重要的一点就是了解 ...
- 【安装虚拟机三】设置Linux IP地址
环境 VMware 10 CentOS-6.5-x86_64 第一步:查看IP信息linux:ifconfig (windows:ipconfig) 第二步:编辑网卡信息 vi /etc/syscon ...
- 给定一个正整数,实现一个方法求出离该整数最近的大于自身的 换位数 <把一个整数各个数位进行全排列>
"""给定一个正整数,实现一个方法求出离该整数最近的大于自身的 换位数 -> 把一个整数各个数位进行全排列""" # 使用 permu ...