“深圳计算科研院杯“E起来编程暨第三届湖北省赛(BDF)
Posted K2MnO4
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了“深圳计算科研院杯“E起来编程暨第三届湖北省赛(BDF)相关的知识,希望对你有一定的参考价值。
B.Mr.Maxwell and attractions
- 题目链接:Mr.Maxwell and attractions
- 题意:某人所在的城市有室内景观和室外景观,每种景观都有一个观赏值,每种景观在观赏时可以得到观赏值val,观赏后,其观赏值将变为原值60%(0.6val),但室外景观若在下午观赏,其观赏时只可获得本次观赏值的80%,也就是0.8val,观赏后,其观赏值一样变为原值60%(0.6val),而某人有t天可以观赏,并且必须至少有k天在下午观赏,问某人能得到的最大观赏值.
ps:比如一室外景观观赏初值为8,若在早上观赏(第一次)则可获得观赏值8,若在下午观赏,仅可获得8 * 0.8 = 6.4的观赏值,但他们观赏后该景观的观赏值均变为8 * 0.6 = 4.8。 - 思路:贪心 + 动态维护
- 解析:因为室外景观在下午观赏会贬值,所以我们尽可能的都选择上午观赏,而室内景观上下午均不会贬值。
- 若剩余观赏天数 <= k 说明此时必须下午观赏,这时候比较当前室内景观最大的观赏值与室外景观最大的观赏值 * 0.8,谁大观赏谁;
- 若剩余观赏天数 > k说明上下午进行观赏均可,这时候比较当前室内景观最大的观赏值与室外景观最大的观赏值,若室内景观最大观赏值大,我们就将其放到下午观赏(室内景观上下午都不会贬值,而室外景观下午会贬值80%),若室外景观最大观赏值大则将室外景观放到上午观赏(尽可能让室外景观上午观赏)
- 代码一:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#define debug(x) cout << "****" << x << endl
using namespace std;
int n, m, t, k;
double res = 0.0;
priority_queue<double> iq;
priority_queue<double> oq;
int main()
{
cin >> n >> m >> t >> k;
for(int i = 1; i <= n; i++)
{
double x;
cin >> x;
iq.push(x);
}
for(int i = 1; i <= m; i++)
{
double x;
cin >> x;
oq.push(x);
}
while(t --)
{
double val1 = iq.top();
double val2 = oq.top();
if(t < k) //必须下午参观
{
if(0.8 * val2 > val1) //参观室外景观
{
oq.pop();
res += 0.8 * val2;
oq.push(0.6 * val2);
}
else
{
iq.pop();
res += val1;
iq.push(0.6 * val1);
}
k --;
}
else //上午下午都可以参观
{
if(val1 >= val2) //为了不让室外景观贬值,尽可能的选择室内景观下午参观
{
iq.pop();
res += val1;
iq.push(0.6 * val1);
k --;
}
else //不让室外景观贬值,让室外景观上午参观
{
oq.pop();
res += val2;
oq.push(0.6 * val2);
}
}
}
printf("%.2lf\\n", res);
return 0;
}
- 代码二(思路和代码一相同,只是将其拆分成上午、下午参观):
#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#define debug(x) cout << "****" << x << endl
using namespace std;
const int N = 1e4 + 5;
int n, m, t, k;
double res = 0.0;
priority_queue<double> iq;
priority_queue<double> oq;
int main()
{
cin >> n >> m >> t >> k;
for(int i = 1; i <= n; i++)
{
double x;
cin >> x;
iq.push(x);
}
for(int i = 1; i <= m; i++)
{
double x;
cin >> x;
oq.push(x);
}
t -= k; //t-k天选择上午或下午均可(尽可能早上)
//必须先考虑上午旅游的情况,因为室外景观在下午欣赏值会贬值
while(t --) //室内景观上午下午都是60%喜悦值,而室外下午还会减少20%(早上为60%),所以尽可能都选早上参观
{
double val1 = iq.top();
double val2 = oq.top();
if(!k) //假如不一定要下午参观
{
if(val2 >= val1)
{
res += val2;
oq.pop();
oq.push(0.6 * val2);
}
else
{
res += val1;
iq.pop();
iq.push(0.6 * val1);
}
}
else
{
if(val2 >= val1)
{
res += val2;
oq.pop();
oq.push(0.6 * val2);
}
else if(val1 > val2)
{
res += val1;
iq.pop();
iq.push(0.6 * val1);
t ++;
k -- ;//既然室内景观比室外的欣赏值高,那干脆放到下午去看,反正欣赏值都一样,尽可能不让室外景观贬值
}
}
}
while(k --) //剩下的k天必须下午去
{
double val1 = iq.top();
double val2 = oq.top();
if(0.8 * val2 >= val1)
{
res += 0.8 * val2;
oq.pop();
oq.push(0.6 * val2);
}
else
{
res += val1;
iq.pop();
iq.push(0.6 * val1);
}
}
printf("%.2lf\\n", res);
return 0;
}
D.WA
- 题目链接:WA
- 题意:给出一个字符串,有k次操作可以将不是a的字符替换成a,问操作后的字符串最多能有几个\'aa\'的子串
- 思路:贪心 + 模拟
- 解析:先找出有多少个ax...xa这样的序列,从小到大按起点为a终点也为a的序列长度排序,从长度最小的序列将不是a的字符替换成a,最后序列若两个a中没有夹有其他字符并且还有可以将字符替换成a的次数,那么则找到这个xx..aaa(不一定是3个a可能1个、2个)..xx的序列,从第一个a的左侧和最后一个a的右侧依次将字符替换成a即可。
- 代码:
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const int N = 5e5 + 5;
struct Node
{
int b = 0, e = 0, num = 0;
}p[N];
int n, k, cnt = 0, res = 0, acnt = 0;
string str;
bool cmp(Node a, Node b)
{
return a.num < b.num;
}
int main()
{
cin >> n >> k;
cin >> str;
int flag = 0;
for(int i = 1; i < str.length(); i++)
{
if(!flag && str[i] != \'a\' && str[i-1] == \'a\')
{
p[++cnt].b = i;
p[cnt].num ++;
flag = 1;
}
else if(flag && str[i] == \'a\')
{
p[cnt].e = i - 1;
flag = 0;
}
else if(flag && str[i] != \'a\')
p[cnt].num ++;
}
if(p[cnt].e == 0) cnt --; //特判最后一个区间是不是没有被一个a包住
if(cnt > 0) //判断是否有被两个a包围的区间
{
sort(p + 1, p + 1 + cnt, cmp); //将被两个a包住区间长度从小到大排序,从最小的开始替换a(可能为aaa,所以判断cnt)
for(int i = 1; i <= cnt; i++)
{
if(!k) break;
for(int j = p[i].b; j <= p[i].e; j++)
{
str[j] = \'a\';
k --;
if(!k) break;
}
}
}
if(k) //剩余k说明当前所有的a肯定是连在一起的
{
int afpos = -1; //第一个a
int alpos = -1; //最后一个a
for(int i = 0; i < str.length(); i++)
{
if(str[i] == \'a\' && afpos == -1) afpos = i;
else if(str[i] == \'a\' && afpos != -1) alpos = i;
}
if(acnt == 1) alpos = afpos; //只有一个a起始点与终点一致
for(int i = afpos - 1; i >= 0 && k; i--) //从第一个a开始往左更新
{
str[i] = \'a\';
k --;
}
for(int i = alpos + 1; i < str.length() && k; i++) //从最后一个a往右更新
{
str[i] = \'a\';
k --;
}
}
for(int i = 1; i < str.length(); i++)
if(str[i] == \'a\' && str[i-1] == \'a\') res ++;
cout << res << endl;
cout << str << endl;
return 0;
}
/*
5 2
bbaac
*/
E.Meet in another world, enjoy tasty food!
- 题目:Meet in another world, enjoy tasty food!
- 题意:有n个人在排队,每个人的忍耐值是xi,但现在每隔一段时间就会有一个操作:从第1个人-> 第n个人,每个人的忍耐值将会减掉它所在的位置号(从1开始到n),若此时xi <= 0,则此人离开队列,并且它之后的所有人将向前移动一个位置,而此时它身后的人忍耐值减掉的值将是新的位置号,最后要求输出依次离开的人的原位置编号.
- 思路:思维 + 模拟区间维护
- 解析:首先每个人实际能存活的操作轮数为res = ceil(xi / 当前位置号pos),然后找出最小值(若相等,则编号小的先离开),此时需要对离开的人前后的人([1, pos-1], [pos+1, n]这两个区间)进行维护:
- 区间为:[1, pos-1]
实际上这个区间的人也进行res次循环操作,所以其忍耐值xi -> xi - res * 其当前位置号,但其需要离开的最少操作循环次数为:ceil(xi / 当前位置号pos) + 1,加1的原因其实是因为此轮其实已经遍历经过[1, pos-1],而[pos + 1, n]仍未遍历完成 - 区间为:[pos+1, n]
实际上这个区间的人仅进行(res - 1)次循环操作,所以其忍耐值xi -> xi - (res - 1) * 其当前位置号,然后需要将其向前移动一位,其需要离开的最少操作循环次数为:ceil(xi / 新的当前位置号)
- 区间为:[1, pos-1]
- 代码:
#include<iostream>
#include<cmath>
using namespace std;
const int N = 1005;
typedef long long ll;
int n;
struct Node
{
int id = 0; //初始编号
double val = 0;
ll t = 0; //需要循环t次将离开队伍
}a[N];
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i].val;
a[i].id = i;
a[i].t = ceil(a[i].val / (double)i);
}
while(n)
{
int pos = 1; //当前最先离开的人的位置
double res = a[1].t; //当前最先离开的人需循环的总次数
for(int i = 1; i <= n; i++) //找出当前最先离开队伍的人(循环次数一样编号小的先离开)
{
if(a[i].t < res)
{
pos = i;
res = a[i].t;
}
}
cout << a[pos].id << " "; //输出离开的人编号
for(int i = 1; i <= pos - 1; i++) //维护1 - (pos - 1)的人
{
a[i].val -= i * res; //总共循环res次
a[i].t = ceil(a[i].val / (double)i) + 1; //+1:当前起点从pos开始
}
for(int i = pos; i <= n - 1; i++) //维护(pos + 1) - n的人
{
a[i+1].val -= (i + 1) * (res - 1); //总共循环res-1次
a[i].val = a[i+1].val; //位置向前移
a[i].id = a[i+1].id; //编号不变
a[i].t = ceil(a[i].val / (double)i);
}
n --; //人数不断减少
}
return 0;
}
以上是关于“深圳计算科研院杯“E起来编程暨第三届湖北省赛(BDF)的主要内容,如果未能解决你的问题,请参考以下文章
“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛 E
“盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛题解&&源码A,水,B,水,C,水,D,快速幂,E,优先队列,F,暴力,G,贪心+排序,H,STL乱搞,I,尼姆博(
“今日头条杯”首届湖北省大学程序设计竞赛(网络同步赛 )--B. Salty Fish Go!
CCPC2019河北省赛 E.Paper Plane Fly Away