A. Points on the line

题意

给定一条直线上\(n\)个点,要求去掉最少的点,使得直线上相距最远的两个点的距离\(\leq d\).

思路

枚举长度为\(d\)的区间。

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
typedef long long LL;
int a[110];
int main() {
int n, d;
scanf("%d%d", &n, &d);
F(i, 0, n) {
int x;
scanf("%d", &x);
++a[x];
}
F2(i, 1, 100) a[i] += a[i-1];
int ans = min(a[100]-a[d], a[99-d]);
F(i, 1, 100-d) {
int l = i, r = i+d;
ans = min(ans, a[l-1]+a[100]-a[r]);
}
printf("%d\n", ans);
return 0;
}

B. Our Tanya is Crying Out Loud

题意

初始数为\(n\),两种操作:

  1. 减一:代价为\(A\)
  2. 除以\(k\):代价为\(B\)且仅当整除时可进行此操作

求最小代价使\(n\)变为\(1\).

思路

一旦某一次除法的代价\(\gt\)减法的(等效)代价,则直接减到\(1\),否则进行除法操作。

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
using namespace std;
typedef long long LL;
int main() {
LL n,k,a,b;
scanf("%I64d%I64d%I64d%I64d",&n,&k,&a,&b);
LL ans = 0;
bool flag = false;
while (n!=1) {
if (n%k) {
ans += n%k*a;
n = n/k*k;
}
if (n/k*(k-1)*a <= b) {
ans += (n-1)*a;
break;
}
ans += b;
n /= k;
}
printf("%I64d\n", ans);
return 0;
}

C. Phone Numbers

题意

在字符集\(\sum\)范围内,求长度为\(k\)的,比给定字符串\(s\)大的,最小的字符串。

思路

记\(len=|s|\),

  1. 若\(len<k\),在\(s\)之后补\(k-len\)个最小的字符
  2. 若\(len>k\),首先将之后的多余部分截断,再将前面的部分 加一(操作与数字+1同理)。

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 100010
using namespace std;
typedef long long LL;
char s[maxn];
int mp[256], ch[30], a[maxn];
bool vis[256];
int main() {
int n, k, tot=0;
scanf("%d%d", &n,&k);
scanf("%s",s);
int len = strlen(s);
F(i, 0, len) {
if (tot==26) break;
if (!vis[s[i]]) {
ch[tot++] = s[i];
vis[s[i]] = true;
}
}
sort(ch, ch+tot);
F(i, 0, tot) mp[ch[i]] = i;
if (k>len) {
while (len<k) s[len++] = ch[0];
s[len] = '\0';
puts(s);
return 0;
}
s[k] = '\0';
F(i, 0, k) a[i] = mp[s[i]];
int i = k-1;
while (true) {
++a[i];
if (a[i]<tot) break;
a[i--] = 0;
}
F(i, 0, k) s[i] = ch[a[i]];
puts(s);
return 0;
}

D. Alena And The Heater

题意

给定数组\(a\),按一定的规则可以生成数组\(b\). 规则如下:

  • \(b_1=b_2=b_3=b_4=0.\)
  • For all \(5\leq i\leq n\):

    --- \(b_i=0\) if \(a_i,a_{i-1},a_{i-2},a_{i-3},a_{i-4}\gt r\) and \(b_{i-1},b_{i-2},b_{i-3},b_{i-4}=1\)

    --- \(b_i=1\) if \(a_i,a_{i-1},a_{i-2},a_{i-3},a_{i-4}\lt l\) and \(b_{i-1},b_{i-2},b_{i-3},b_{i-4}=0\)

    --- \(b_i=b_{i-1}\) otherwise

思路

只需确定每个转折点,对于其及其前面共\(5\)个数字,由\(1\)变为\(0\)则取最小值使\(r\)比它小,由\(0\)变为\(1\)则取最大值使\(l\)比它大。

至于中间则无需考虑,因为题目保证有解,而要不发生变化,即条件不成立,则只要\(l\)尽量小,\(r\)尽量大即可。

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define inf 1000000000
#define maxn 100010
using namespace std;
char s[maxn];
int a[maxn];
typedef long long LL;
int minn(int p) { int ret = a[p]; F(i, p+1, p+5) ret = min(ret, a[i]); return ret; }
int maxx(int p) { int ret = a[p]; F(i, p+1, p+5) ret = max(ret, a[i]); return ret; }
int main() {
int n;
scanf("%d", &n);
F(i, 0, n) scanf("%d", &a[i]);
scanf("%s", s);
bool flag = false;
int r = inf, l = -inf;
F(i, 0, n) {
if (s[i]-'0'!=flag) {
if (flag) r = min(r, minn(i-4)-1);
else l = max(l, maxx(i-4)+1);
flag = !flag;
}
}
printf("%d %d\n", l, r);
return 0;
}

E. Cashback

题意

给定一个数组,将其分割成若干段,将每一段的\(value\)求和,要求得最小值。

\(value\)定义如下:

对于长度为\(k\)的数组\(b\),其\(value\)为除了\(\lfloor\frac{k}{c}\rfloor\)小元素以外的元素的和。

例如:[3,1,6,5,2], c=2,其value为3+6+5=14.

思路

首先一个显然的事实是:假设不分段而作为一个整体能去除掉\(m\)个元素,那分段去除掉的元素个数必然\(\leq m\).

然而又有另一个显然的事实:不分段去掉\(m\)个元素之和\(sum1\),与分段去掉\(m\)个元素\(sum2\)相比,显然\(sum1\leq sum2\). 因为不分段的话去掉的是一整段的\(m\)个最小,而分段的话去掉的是\(m\)段中每段中的最小。

综合上面两个事实,应该尽量多分段,又要保证每一段分的有价值,即,最理想的情况就是每\(c\)个元素分一段。

于是\(dp\)如下:

\(dp[i] = min(dp[i-1]+a[i], dp[i-c]+sum[i-c+1..i]-min[i-c+1..i])\)

至于最小值,直接用ST表进行RMQ即可,比赛时用的是单调队列维护的...。

Code

#include <bits/stdc++.h>
#define F(i, a, b) for (int i = (a); i < (b); ++i)
#define F2(i, a, b) for (int i = (a); i <= (b); ++i)
#define dF(i, a, b) for (int i = (a); i > (b); --i)
#define dF2(i, a, b) for (int i = (a); i >= (b); --i)
#define maxn 100010
using namespace std;
typedef long long LL;
LL a[maxn], sum[maxn], dp[maxn];
int st[maxn];
int main() {
int n, c;
scanf("%d%d", &n, &c);
F2(i, 1, n) {
scanf("%I64d", &a[i]);
sum[i] = sum[i-1] + a[i];
}
if (c==1) { printf("%d\n", 0); return 0; }
dp[1] = a[1];
int l=0, r=0; st[r++] = 1;
F2(i, 2, n) {
LL minn = dp[i-1]+a[i];
while (r>l && a[st[r-1]]>=a[i]) --r;
st[r++] = i;
if (i-c>=0) {
while (r>l && st[l]<=i-c) ++l;
minn = min(minn, dp[i-c]+sum[i]-sum[i-c]-a[st[l]]);
}
dp[i] = minn;
}
printf("%I64d\n", dp[n]);
return 0;
}

Codeforces Round #466的更多相关文章

  1. Codeforces Round #466 (Div. 2) E. Cashback

    Codeforces Round #466 (Div. 2) E. Cashback(dp + 贪心) 题意: 给一个长度为\(n\)的序列\(a_i\),给出一个整数\(c\) 定义序列中一段长度为 ...

  2. Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F

    Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...

  3. 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 ...

  4. Codeforces Round #466 (Div. 2)

    所有的题目都可以在CodeForces上查看 中间看起来有很多场比赛我没有写了 其实是因为有题目没改完 因为我不想改,所以就没有写了(大部分题目还是改完了的) 我还是觉得如果是打了的比赛就一场一场写比 ...

  5. Codeforces Round #466 (Div. 2) Solution

    从这里开始 题目列表 小结 Problem A Points on the line Problem B Our Tanya is Crying Out Loud Problem C Phone Nu ...

  6. 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 ...

  7. Codeforces Round #466 (Div. 2) 题解

    人生中第三次\(CF\)... 考试中切了\(A\)~\(E\) \(F\)题会做没时间写 题解 A:Points on the line 题意 给定一个数列,删最小的数,使最大差不大于一个定值 So ...

  8. 【Codeforces Round #466】E. Cashback DP+ST表

    题意 给定$n$个数,将其划分成若干个连续的子序列,求最小价值,数组价值定义为,数组和减去$\lfloor \frac{k}{c} \rfloor$,$k$为数组长度,$c$为给定数 可以列得朴素方程 ...

  9. Codeforces Round #466 (Div. 2) B. Our Tanya is Crying Out Loud[将n变为1,有两种方式,求最小花费/贪心]

    B. Our Tanya is Crying Out Loud time limit per test 1 second memory limit per test 256 megabytes inp ...

随机推荐

  1. ConcurrentHashMap原理分析(1.7与1.8)-put和 get 需要执行两次Hash

    ConcurrentHashMap 与HashMap和Hashtable 最大的不同在于:put和 get 两次Hash到达指定的HashEntry,第一次hash到达Segment,第二次到达Seg ...

  2. BZOJ 1222 产品加工(DP)

    某加工厂有A.B两台机器,来加工的产品可以由其中任何一台机器完成,或者两台机器共同完成.由于受到机器性能和产品特性的限制,不同的机器加工同一产品所需的时间会不同,若同时由两台机器共同进行加工,所完成任 ...

  3. 关于qt中的tr()函数

    关于qt中的tr()函数 在论坛中漂,经常遇到有人遇到tr相关的问题.用tr的有两类人: (1)因为发现中文老出问题,然后搜索,发现很多人用tr,于是他也开始用tr (2)另一类人,确实是出于国际化的 ...

  4. byte数组转float实现与byte转换其它类型时进行&运算原理

    下面是将byte数组转换为float的实现 public static float getFloat(byte[] b) { int accum = 0; accum = accum|(b[0] &a ...

  5. KMP算法复习【+继续学习】

    离NOIP还剩12天,本蒟蒻开始准备复习了. 先来个KMP[似乎我并没有写过KMP的blog] KMP KMP算法是解决字符串匹配问题的一个算法,主要是单对单的字符串匹配加速,时间复杂度O(m + n ...

  6. Java之基础20160806

    注意这里介绍的JAVA基础是指你对C语言已经比较熟练或者有一定基础了,再学习如下这知识就会比较快. 1.JAVA也是从MAIN开始执行,但是要先定义类,文件名要与类名一致并且类名首字母要大写,同时JA ...

  7. Dom4j 操作, 节点查找 添加 删除 修改 。。。xPath

    转: Dom4j 操作, 节点查找 添加 删除 修改 ...xPath 2013年11月28日 10:48:59 今晚打酱油8 阅读数:8506更多 个人分类: JavaWeb   版权声明:本文为博 ...

  8. HDU4388:Stone Game II(博弈+思维)

    Stone Game II Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  9. javascript和bigint

    http://note.youdao.com/noteshare?id=91e21eb1d8c20025d72d7ee6f401e34d

  10. 手脱EXE32Pack v1.39

    1.PEID查壳 EXE32Pack v1.39 2.载入OD,先F8跟一下 0040A00C > 3BC0 cmp eax,eax ; //程序入口点 0040A00E je short st ...