Codeforces Round #466 (Div. 2) 题解
人生中第三次\(CF\)。。。
考试中切了\(A\)~\(E\)
\(F\)题会做没时间写
题解
A:Points on the line
题意
给定一个数列,删最小的数,使最大差不大于一个定值
Sol
排序后选的一定是段连续的区间,枚举左右端点即可
手速慢了233
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(105);
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
int n, d, x[_], ans;
int main(RG int argc, RG char* argv[]){
n = Input(), d = Input();
for(RG int i = 1; i <= n; ++i) x[i] = Input();
sort(x + 1, x + n + 1);
if(!n || x[n] - x[1] <= d) return puts("0"), 0;
for(RG int i = 1; i <= n; ++i)
for(RG int j = i; j <= n; ++j)
if(x[j] - x[i] <= d) ans = max(ans, j - i + 1);
printf("%d\n", n - ans);
return 0;
}
B:Our Tanya is Crying Out Loud
题意
给定数\(n\)和\(k\)以及代价\(A\)和\(B\)
你可以花\(A\)的代价给\(n\)减\(1\)
或者当\(n\)为\(k\)的倍数时花\(B\)的代价把\(n\)变为\(n/k\)
问\(n\)变为\(1\)的最小代价
Sol
不是\(k\)的倍数,就减到\(k\)的倍数为止
否则比较减和除的代价,取最小
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(105);
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
int n, k, a, b;
ll ans = 0;
int main(RG int argc, RG char* argv[]){
n = Input(), k = Input(), a = Input(), b = Input();
if(k == 1){
cout << 1LL * a * (n - 1) << endl;
return 0;
}
while(n >= k){
RG int t = n / k, tt = n % k;
n -= tt;
ans += 1LL * tt * a;
ans += min(1LL * b, 1LL * (n - t) * a);
n = t;
}
ans += 1LL * a * (n - 1);
cout << ans << endl;
return 0;
}
C:Phone Numbers
题意
一个长度为\(n\)的小写字母组成的字符串和一个整数\(k\),要你生成一个最小字典序的长度为\(k\)的小写字母组成的字符串
使该字符串的字符集为给定串的字符集的子集,并且字典序大于给定串
Sol
找到一个最后面的位置可以使答案串大于原串,后面直接填最小的字符
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(1e5 + 5);
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
int n, k, t[30], pos, g[30];
char s[_];
int main(RG int argc, RG char* argv[]){
n = Input(), k = Input();
scanf(" %s", s + 1), s[n + 1] = 'a' - 1;
for(RG int i = 1; i <= n; ++i) ++t[s[i] - 'a'];
for(RG int i = 25; ~i; --i) g[i] = t[i], t[i] += t[i + 1];
for(RG int i = min(k, n + 1); i; --i)
if(t[s[i] - 'a' + 1]){
pos = i;
break;
}
for(RG int i = 1; i < pos; ++i) printf("%c", s[i]);
for(RG int i = s[pos] - 'a' + 1; i < 26; ++i)
if(g[i]){
printf("%c", i + 'a');
break;
}
RG int tmp = 0;
for(RG int i = 0; i < 26; ++i)
if(g[i]){
tmp = i;
break;
}
for(RG int i = pos + 1; i <= k; ++i) printf("%c", tmp + 'a');
return 0;
}
D:Alena And The Heater
题意
给定数列\(A\)
以及生成数列\(B\)的条件:
\(B[1]=B[2]=B[3]=B[4]=0\)
对于\(i>4\)
如果
\(a[i],a[i-1],a[i-2],a[i-3],a[i-4]>r\)
且\(b[i-1]=b[i-2]=b[i-3]=b[i-4]=1\)
则\(b[i]=1\)
如果
\(a[i],a[i-1],a[i-2],a[i-3],a[i-4]<l\)
且\(b[i-1]=b[i-2]=b[i-3]=b[i-4]=0\)
则\(b[i]=0\)
否则\(b[i]=b[i-1]\)
保证一定有解,输出\(l, r\)可以构造出给定的数列\(B\)
输出任意一组\(l,r\in[-1e9, 1e9]\)
Sol
保证一定有解,那么按题意反过来构造\(l, r\)即可
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(1e5 + 5);
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
int n, a[_], b[_], l = -1e9, r = 1e9;
char s[_];
int main(RG int argc, RG char* argv[]){
n = Input();
for(RG int i = 1; i <= n; ++i) a[i] = Input();
scanf(" %s", s + 1);
for(RG int i = 1; i <= n; ++i) b[i] = s[i] - '0';
for(RG int i = 5; i <= n; ++i){
RG int s = b[i - 1] + b[i - 2] + b[i - 3] + b[i - 4];
if(s && s != 4) continue;
if(b[i] == b[i - 1]) continue;
if(b[i]){
RG int mx = -1e9;
for(RG int j = 0; j <= 4; ++j) mx = max(mx, a[i - j]);
l = max(l, mx + 1);
}
else{
RG int mn = 1e9;
for(RG int j = 0; j <= 4; ++j) mn = min(mn, a[i - j]);
r = min(r, mn - 1);
}
}
printf("%d %d\n" ,l, r);
return 0;
}
E:Cashback
题意
给定一个长度为\(n\)的数列以及一个整数\(c\)
一个下标在\([l, r]\)内的子数列的价值为所有数的和减去子数列中前\(\lfloor\frac{r-l+1}{c}\rfloor\)小的数的和
求把这个数列分成若干个块,使的每块的价值和最小
Sol
前\(k\)小?离散化+主席树辣
码完
发现只会\(n^2\)的滴劈
设\(f[i]\)表示做到第\(i\)个数的最小代价,枚举长度转移,前\(k\)小的和主席树查询
你当这是\(OI\)赛制啊?没有部分分的。。
我们分情况考虑
- 若分一块长度小于\(c\)的
价值就是所有的数的和
那么还不如一个一个选更方便转移 - 若分一块长度为\(c\)的倍数的
我们把它分成若干个长度为\(c\)的块,就是总和减去每个块的最小值的和
而直接分一块就是总和减去整个块的前几个最小值
整个块的前几个最小值一定小于等于若干块的最小值和
那么分成若干个长度为\(c\)的块最优 - 若一块长度大于等于\(c\)的,就是上面两种组合而来
那么策略就是:要么一个一个选,要么选\(c\)个一块
只要求区间最小值,\(RMQ\)问题
然而主席树懒得删
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(1e5 + 5);
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
int n, c, tot, len, rt[_];
ll f[_], s[_], o[_], a[_];
struct HJT{
int sz, rs, ls;
ll sum;
} T[_ * 20];
IL void Modify(RG int &x, RG int l, RG int r, RG int id, RG ll v){
T[++tot] = T[x], T[x = tot].sum += v, ++T[x].sz;
if(l == r) return;
RG int mid = (l + r) >> 1;
if(id <= mid) Modify(T[x].ls, l, mid, id, v);
else Modify(T[x].rs, mid + 1, r, id, v);
}
IL ll Query(RG int A, RG int B, RG int l, RG int r, RG int k){
if(l == r) return o[l];
RG int mid = (l + r) >> 1, ss = T[T[B].ls].sz - T[T[A].ls].sz;
RG ll sss = T[T[B].ls].sum - T[T[A].ls].sum;
if(ss >= k) return Query(T[A].ls, T[B].ls, l, mid, k);
else return sss + Query(T[A].rs, T[B].rs, mid + 1, r, k - ss);
}
int main(RG int argc, RG char* argv[]){
n = Input(), c = Input(), Fill(f, 127), f[0] = 0;
for(RG int i = 1; i <= n; ++i) o[i] = a[i] = Input(), s[i] = s[i - 1] + a[i];
sort(o + 1, o + n + 1), len = unique(o + 1, o + n + 1) - o - 1;
for(RG int i = 1; i <= n; ++i){
RG int p = lower_bound(o + 1, o + len + 1, a[i]) - o;
rt[i] = rt[i - 1], Modify(rt[i], 1, len, p, a[i]);
}
for(RG int i = 1; i < c; ++i) f[i] = s[i];
for(RG int i = c; i <= n; ++i){
RG ll sum = s[i] - s[i - c] - Query(rt[i - c], rt[i], 1, len, 1);
f[i] = min(f[i - 1] + a[i], f[i - c] + sum);
}
cout << f[n] << endl;
return 0;
}
F:Machine Learning
题意
给一个数列
每次询问一个区间\([l,r]\)
求数列下标在这个区间内的数的个数的\(mex\)值
\(p.s\):\(mex\)值是最小的没出现的整数值
数会随时修改
Sol
这不就是离散化+带修改莫队吗?
吐槽一下:
\(mex\)值开桶暴力求就能过了
我的做法:
把数字也分块,计算\(mex\)时,找到第一个不满的块,再在块内找的那个\(mex\)值
还有一点就是
我\(TM\)学了假的带修改莫队:
没按时间为第三关键字排序!!!
没把块的大小设为\(n^\frac{2}{3}\)!!!
没比较右端点所在的块!!!
然后一直\(TLE\),\(QAQ\)
# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long ll;
const int _(4e5 + 5);
IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
}
int n, q, bl[_], o[_], len, a[_], ans[_], blo, cnt, tot;
int t[_], sum[5000], size[_];
struct Query{
int l, r, t, id;
IL bool operator <(RG Query B) const{
if(bl[l] != bl[B.l]) return l < B.l;
if(bl[r] != bl[B.r]) return r < B.r;
return t < B.t;
}
} qry[_];
struct Modify{
int p, x;
} mdy[_];
IL void Change(RG int x, RG int d){
if(d > 0){
if(!size[x]) ++sum[x / blo];
++size[x];
}
else{
--size[x];
if(!size[x]) --sum[x / blo];
}
}
IL int Mex(){
for(RG int i = 0; ; ++i)
if(sum[i] != blo){
for(RG int j = 0; j < blo; ++j)
if(!size[i * blo + j]) return i * blo + j;
}
}
IL void Calc(RG int v, RG int d){
Change(t[v], -1), t[v] += d, Change(t[v], 1);
}
IL void Adjust(RG int j, RG int l, RG int r){
if(mdy[j].p >= l && mdy[j].p <= r) Calc(a[mdy[j].p], -1);
swap(a[mdy[j].p], mdy[j].x);
if(mdy[j].p >= l && mdy[j].p <= r) Calc(a[mdy[j].p], 1);
}
int main(RG int argc, RG char* argv[]){
n = Input(), q = Input(), blo = pow(n, 2.0 / 3.0);
for(RG int i = 1; i <= n; ++i) o[++len] = a[i] = Input(), bl[i] = (i - 1) / blo;
for(RG int i = 1; i <= q; ++i){
RG int op = Input(), x = Input(), y = Input();
if(op == 1) qry[++cnt] = (Query){x, y, tot, cnt};
else mdy[++tot] = (Modify){x, y}, o[++len] = y;
}
sort(o + 1, o + len + 1), len = unique(o + 1, o + len + 1) - o - 1;
for(RG int i = 1; i <= n; ++i)
a[i] = lower_bound(o + 1, o + len + 1, a[i]) - o;
for(RG int i = 1; i <= tot; ++i)
mdy[i].x = lower_bound(o + 1, o + len + 1, mdy[i].x) - o;
sort(qry + 1, qry + cnt + 1), blo = sqrt(len);
for(RG int L = qry[1].l, R = qry[1].l - 1, i = 1, j = 0; i <= cnt; ++i){
while(L < qry[i].l) Calc(a[L++], -1);
while(L > qry[i].l) Calc(a[--L], 1);
while(R < qry[i].r) Calc(a[++R], 1);
while(R > qry[i].r) Calc(a[R--], -1);
while(j < qry[i].t) Adjust(++j, L, R);
while(j > qry[i].t) Adjust(j--, L, R);
ans[qry[i].id] = Mex();
}
for(RG int i = 1; i <= cnt; ++i) printf("%d\n", ans[i]);
return 0;
}
总结
\(CF\)比赛的题还是不错的
总有一些奇奇怪怪的脑洞
话说歪果仁知道主席树和莫队算法吗?
Codeforces Round #466 (Div. 2) 题解的更多相关文章
- Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F
Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...
- Codeforces Round #182 (Div. 1)题解【ABCD】
Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...
- Codeforces Round #466 (Div. 2) E. Cashback
Codeforces Round #466 (Div. 2) E. Cashback(dp + 贪心) 题意: 给一个长度为\(n\)的序列\(a_i\),给出一个整数\(c\) 定义序列中一段长度为 ...
- Codeforces Round #608 (Div. 2) 题解
目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 ...
- Codeforces Round #525 (Div. 2)题解
Codeforces Round #525 (Div. 2)题解 题解 CF1088A [Ehab and another construction problem] 依据题意枚举即可 # inclu ...
- Codeforces Round #528 (Div. 2)题解
Codeforces Round #528 (Div. 2)题解 A. Right-Left Cipher 很明显这道题按题意逆序解码即可 Code: # include <bits/stdc+ ...
- Codeforces Round #677 (Div. 3) 题解
Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...
- Codeforces Round #665 (Div. 2) 题解
Codeforces Round #665 (Div. 2) 题解 写得有点晚了,估计都官方题解看完切掉了,没人看我的了qaq. 目录 Codeforces Round #665 (Div. 2) 题 ...
- Codeforces Round #160 (Div. 1) 题解【ABCD】
Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...
随机推荐
- python爬虫(7)——BeautifulSoup
今天介绍一个非常好用的python爬虫库--beautifulsoup4.beautifulsoup4的中文文档参考网址是:http://beautifulsoup.readthedocs.io/zh ...
- [Python Study Notes]CS架构远程访问获取信息--SERVER端v2.0
更新内容: 1.增加内存信息获取 2.增加电池信息获取 3.增加磁盘信息获取 4.重新布局窗体 5.增加窗体名称 6.增加连接成功之前,不可按压 ''''''''''''''''''''''''''' ...
- CentOS常用命令大全
一:使用CentOS常用命令查看cpumore /proc/cpuinfo | grep "model name" grep "model name" /pro ...
- configure: error: Bundled APR requested but not found at ./srclib/. Download and unpack the corresponding apr and apr-util packages to ./srclib/.
Apache在2.4版本以后,编译时: # ./configure \ --prefix=/usr/local/apache2 \ --with-included-apr \ --enable-so ...
- PHP读取大文本文件并处理数据的思路
//处理文件 $file = fopen($filename, "r") or exit("Unable to open file!"); $total_lin ...
- 在Windows下为PHP5.5安装redis扩展
使用phpinfo()函数查看PHP的版本信息,这会决定扩展文件版本 根据PHP版本号,编译器版本号和CPU架构, 选择php_redis-2.2.5-5.5-ts-vc11-x86.zip和ph ...
- 洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication【最小割】分析+题解代码
洛谷P1345 [USACO5.4]奶牛的电信Telecowmunication[最小割]分析+题解代码 题目描述 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流. ...
- 使用Python管理数据库
使用Python管理数据库 这篇文章的主题是如何使用Python语言管理数据库,简化日常运维中频繁的.重复度高的任务,为DBA们腾出更多时间来完成更重要的工作.文章本身只提供一种思路,写的不是很全 ...
- Qt 如何使用 lambda 表达式连接信号和槽?
connect(camera, static_cast<void(QCamera::*)(QCamera::LockStatus, QCamera::LockChangeReason)>( ...
- Qt 网络模块如何使用?
1.网络模块介绍 类名 说明 中文 QAbstractNetworkCache The interface for cache implementations 缓存实现的接口 QNetworkCach ...