Codeforces Round #702 (Div. 3)A-G题解
比赛链接:https://codeforces.ml/contest/1490

这场F读错题意白给一发,G二分的if(dp[mid]<x)居然写成了if(dp[l]<x),做梦都没想到自己二分有写错的一天,疯狂白给5发。

Div3相对以前变简单了,罚时手速场。

A题
暴力

题意:
1000组数据
给定一个只包含正整数的长度为n的数组(n最大50),每个数字均在1到50之间。
你可以在任意位置插入任意的整数(这里其实有bug,你如果插入一个负数那怎么都满足了,题目要求的应该是正整数)。
问最少需要插入多少个数字,使得该数组每一对相邻的两个数字,都满足大的那个不超过小的那个的2倍。

思路:
数值都非常小,直接暴力检测每一对相邻的数字,贪心对小的那个数不断乘2翻倍直到大于等于大的那个数即可。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int maxn=1e6+7;
const double eps=1e-6;
const int mod=1e9+7;int main()
{IOSint t;cin>>t;while(t--){int n;cin>>n;vector<int>num(n);for(int i=0;i<n;i++) cin>>num[i];int ans=0;for(int i=1;i<n;i++){int x=min(num[i],num[i-1]);int y=max(num[i],num[i-1]);while(x*2<y){ans++;x*=2;}}cout<<ans<<endl;}
}

B题
暴力

题意:
给定一个长度为n的只包含整数的数列,其中n必定能被3整除。
数列中对3取余得到0的数字的个数记为cas0,
数列中对3取余得到1的数字的个数记为cas1,
数列中对3取余得到2的数字的个数记为cas2,
每次操作,你可以将数列中的某个数字的值+1。
问最少经过多少次操作,可以使得cas0=cas1=cas2。

思路:
我们最后的目标是使得cas0=cas1=cas2=n/3。
那么实际上我们就是要把多了的通过+1操作补到少了的cas上去。

如果cas1大于n/3的话,我们可以把多了的部分都+1,让他们变成cas2的值。

cas0,cas1,cas2的具体情况当然是有很多种,但是不论是哪种,都存在[0->1->2]或者[1->2->0]或者[2->0->1]这样的转移顺序使得最后三个cas都为n/3。
直接暴力for两遍0-2的转移即可。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int maxn=1e6+7;
const double eps=1e-6;
const int mod=1e9+7;int main()
{IOSint t;cin>>t;while(t--){int n;cin>>n;vector<int>num(n);int cas[3]={0};for(int i=0;i<n;i++){cin>>num[i];if(num[i]%3==0) cas[0]++;else if(num[i]%3==1) cas[1]++;else cas[2]++;}int ans=0;for(int i=0;i<2;i++)//循环两遍for(int j=0;j<3;j++)if(cas[j]>n/3) {ans+=cas[j]-n/3;cas[(j+1)%3]+=cas[j]-n/3;cas[j]=n/3;}cout<<ans<<endl;}
}

C题
预处理,map

题意:
t组数据,最大100组。
每组数据给定一个1e12以内的正整数x,你需要求出满足a3+b3=x的(a,b)有多少对。

思路:
注意到x最大为1e12,那么a和b的取值最大只有1e4。
我们可以预处理出1到1e4这1e4个整数的三次方为多少,用map记录其是否出现。
每组数据,我们暴力枚举这1e4个三次方,用map检测x减去当前的值,剩下的部分是否也为一个立方数即可。
复杂度为100 × \times × 1e4 × \times × log(1e4)。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int maxn=1e6+7;
const double eps=1e-6;
const int mod=1e9+7;map<ll,int>M;
vector<ll>num;int main()
{IOSint t;cin>>t;for(int i=1;i<=10000;i++){ll x=i;x=x*x*x;M[x]=1;num.push_back(x);}while(t--){bool flag=0;ll x;cin>>x;for(int i=0;i<num.size();i++){if(M.find(x-num[i])!=M.end()) {flag=1;break;}}if(flag) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
}

D题
暴力模拟,dfs

题意:
给定一个长度为n的排列。
你要按照如下的规则将这个排列构造成一棵二叉树,依次输出每个位置在这棵树中的深度是多少。

先把整个排列中最大的数,作为树根。
在原排列中,在当前这个数左侧的所有数都在当前根的左子树中,并且以其中最大的值为子树的根。
在原排列中,在当前这个数右侧的所有数都在当前根的右子树中,并且以其中最大的值为子树的根。
之后左右子树同上进行构造。

思路:
直接dfs模拟这个过程就可以了,分析复杂度会发现最糟糕也就是n2,再乘以数据组数100组也就1e6的级别。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int maxn=1e6+7;
const double eps=1e-6;
const int mod=1e9+7;int num[107];
int deep[107];//deep[i]记录第i个数在树中所在的深度void dfs(int l,int r,int now,int d)//l和r记录当前子树的值在原排列中的下标区间,now为当前作为根的数是哪一个,d代表深度
{if(l==r) return;if(l<now)//处理左区间{int tar=now-1;for(int i=l;i<now-1;i++) if(num[i]>num[tar]) tar=i;deep[tar]=d+1;dfs(l,now-1,tar,d+1);}if(r>now)//处理右区间{int tar=now+1;for(int i=now+2;i<=r;i++) if(num[i]>num[tar]) tar=i;deep[tar]=d+1;dfs(now+1,r,tar,d+1);}
}int main()
{IOSint t;cin>>t;while(t--){int n;cin>>n;for(int i=1;i<=n;i++) cin>>num[i];memset(deep,0,sizeof(deep));int tar=1;for(int i=2;i<=n;i++) if(num[i]>num[tar]) tar=i;deep[tar]=0;dfs(1,n,tar,0);for(int i=1;i<=n;i++) cout<<deep[i]<<' ';cout<<endl;}
}

E题
前缀和,贪心
真是绝了,上场读错了的题意这次居然真的出了这样的题

题意:
给定n个玩家,每个玩家一开始都有若干的代币。
会进行n-1次比拼,每次比拼随机选出两个代币数量不为0的玩家。
如果两个人代币数量不相同,代币多的那个人,拿走两个人的全部代币。
如果两个人代币数量相同,在这两个人中随机选一个人,拿走两个人的所有代币。
最后只剩下一个人。

问有哪些人是有可能是最后剩下的那个人。

思路:
既然说是有可能了,那么我们可以理解为我们可以贪心地去操作比赛的结果,平局的时候我们都令自己选的哪个人获胜。
对于每个人来说,肯定都是先贪心去找其他人当中代币最少的那个去比,如果出现剩下的人中,代币最少的那个也比自己的代币多,那就没办法胜利了。

实际上我们注意到,胜利的人会拿走所有的代币。我们先对着n个人按照代币数量从小到大排序为num[n]数组。随便取一个人,如果他打赢了前i个人的话,那么它当前的代币数量就是num[i]的前缀和。
如果num[i]<num[i+1],则代表这个人无法继续赢下去了。

我们从后往前去找,找到前缀和不足以赢下一个人的位置,就得到了想赢所有人需要的最少代币。输出初始代币数量不少于这个值的人即可。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int maxn=2e5+7;
const double eps=1e-6;
const int mod=1e9+7;ll num[maxn],chuli[maxn],sum[maxn];int main()
{IOSint t;cin>>t;while(t--){int n;cin>>n;for(int i=1;i<=n;i++){cin>>num[i];chuli[i]=num[i];}sort(chuli+1,chuli+n+1);for(int i=1;i<=n;i++) sum[i]=sum[i-1]+chuli[i];//sum为前缀和数组ll bas=chuli[n];//bas记录有可能获胜的人的初始代币最少为多少for(int i=n-1;i>=1;i--){if(sum[i]<chuli[i+1]) break;//如果当前这个人把不比他大的所有人都赢了,此时他已经是剩下的人当中最少的人了//但是他如果赢不了其他人当中最小的那个,那他就没有获胜的希望bas=chuli[i];}vector<int>out;for(int i=1;i<=n;i++)if(num[i]>=bas) out.push_back(i);cout<<out.size()<<endl;for(int i=0;i<out.size();i++) cout<<out[i]<<' ';cout<<endl;}
}

F题
前缀和,暴力
读错题意成既可以删除也可以增加可还行,不过还好只需要删改两三行就可以了

题意:
给定一个长度为n只包含正整数的数组。(n最大2e5)
现在你需要删除尽可能少的数,使得数组中的每个数字出现的次数相同。

思路:
直接暴力枚举最后结果的数组中,每个数字出现了多少次,次数肯定在1到2e5之间。
而每次枚举的计算过程,可以利用前缀和来O(1)实现,具体看代码和注释。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int maxn=2e5+7;
const double eps=1e-6;
const int mod=1e9+7;map<int,int>M;ll cishu[maxn];//cishu[i]记录出现了i次的数字有多少种
ll sumcishu[maxn];//sumcishu为cishu数组的前缀和,记录出现了不超过i次的数字有多少种
ll num[maxn];//num[i]记录出现了i次数字,他们总共出现了几次
ll sumnum[maxn];//sunnum为num数组的前缀和,记录出现了不超过i次的数字,他们总共出现了几次int main()
{IOSint t;cin>>t;while(t--){int n;cin>>n;ll ans=llINF;for(int i=0;i<n;i++){int x;cin>>x;if(M.find(x)==M.end()) M[x]=1;else M[x]++;}for(auto &x:M){cishu[x.second]++;num[x.second]+=x.second;}for(int i=1;i<=n;i++){sumcishu[i]=sumcishu[i-1]+cishu[i];sumnum[i]=sumnum[i-1]+num[i];}for(int i=1;i<=n;i++)//i为我们最后希望数组中剩下的数字,每个数字出现多少次{ll temp=0;temp+=n-sumnum[i]-(sumcishu[n]-sumcishu[i])*i;//对于一开始出现次数大于i次的,我们要把他们减少到i次//sumcishu[n]-sumcishu[i]即为有多少种数字一开始出现次数是大于i次的,他们最后都要变为出现i次,总次数就乘以i//用n-sumnum[i]即为一开始出现次数大于i次的总共出现了几次,减去目标的总次数即为需要删掉的个数temp+=sumnum[i-1];//出现次数小于i的所有数字都要被删掉ans=min(ans,temp);}cout<<ans<<endl;for(int i=1;i<=n;i++) cishu[i]=sumcishu[i]=num[i]=sumnum[i]=0;M.clear();}
}

G题
二分,前缀和,dp
二分函数的mid写成了l是我没想到的,疯狂白给5发,二分居然写错了,青结

题意:
给定n个数字,每次操作都从第一个数字开始,每过一秒,依次加上下一位置的数字,不断循环。

给定m个数字x,问经过多少秒之后,累加的和不小于x。如果永远不可能达到x,输出-1。
n和m最大均为2e5。

思路:
首先用sum[i]记录前i个数字累加起来是多少,mi记录sum数组的最大值。
如果给定的x小于等于mi的话,那么在第一轮循环遍n个数字前便已经结束。我们可以对sum[i]做一个dp,用dp[i]记录sum[1]到sum[i]中最大的值为多少。由此利用二分可在logn的时间找到累加大于等于x的第一个位置。

如果给定的x大于mi的话,就要看后面多次循环后能否达到了。x大于mi,那么x的值至少要被减去x-mi才行。
如果sum[n]<=0的话,代表每次循环结束x的值x与mi的差值并不会减少,因此此时就是无限循环,输出-1即可。
当sum[n]>0时,x-mi至少需要(x-mi)/sum[n]向上取整的循环后才会被减去,再下一轮循环就能达到值x了,同样利用二分来logn时间寻找位置。

#include<bits/stdc++.h>
#define ll long long
#define INF 0x7f7f7f7f //2139062143
#define llINF 9223372036854775807
#define IOS ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
using namespace std;
const int maxn=2e5+7;
const double eps=1e-6;
const int mod=1e9+7;ll num[maxn];
ll sum[maxn];//num数组的前缀和
ll dp[maxn];//dp[i]记录sum[1]到sum[i]中最大的值为多少int search(int n,ll x)
{int l=1,r=n;while(l<r){int mid=(l+r)>>1;if(dp[mid]<x) l=mid+1;else r=mid;}return l;
}int main()
{IOSint t;cin>>t;while(t--){int n,m;cin>>n>>m;ll mi=-1e10;//记录最大的前缀和为多少,也就是依次循环过程中可以得到的最大数值for(int i=1;i<=n;i++){cin>>num[i];sum[i]=sum[i-1]+num[i];dp[i]=max(dp[i-1],sum[i]);mi=max(mi,sum[i]);}while(m--){ll x;cin>>x;if(x>mi){if(sum[n]<=0) cout<<-1<<' ';else{ll cas=(x-mi)/sum[n];if((x-mi)%sum[n]) cas++;x-=cas*sum[n];cout<<cas*n-1+search(n,x)<<' ';}}else cout<<search(n,x)-1<<' ';}cout<<endl;for(int i=1;i<=n;i++) num[i]=sum[i]=dp[i]=0;}
}

Codeforces Round #702 (Div. 3)A-G题解相关推荐

  1. Codeforces Round #702 (Div. 3)解题报告

    Codeforces Round #702 (Div. 3) 全部题解 读错题意,写了半天真是心态爆炸,总的来看这次题目不难的. A. Dense Array http://codeforces.co ...

  2. Codeforces Round #693 (Div. 3)A~G解题报告

    Codeforces Round #693 (Div. 3)A~G解题报告 A Cards for Friends 原题信息 http://codeforces.com/contest/1472/pr ...

  3. Codeforces Round #697 (Div. 3)A~G解题报告

    Codeforces Round #697 (Div. 3)A~G解题报告 题 A Odd Divisor 题目介绍 解题思路 乍一想本题,感觉有点迷迷糊糊,但是证难则反,直接考虑没有奇数因子的情况, ...

  4. Codeforces Round #827 (Div. 4) A~G

     比赛链接:Dashboard - Codeforces Round #827 (Div. 4) - Codeforces 目录 A Sum B Increasing C Stripes D. Cop ...

  5. Codeforces Round #198 (Div. 2)A,B题解

    Codeforces Round #198 (Div. 2) 昨天看到奋斗群的群赛,好奇的去做了一下, 大概花了3个小时Ak,我大概可以退役了吧 那下面来稍微总结一下 A. The Wall Iahu ...

  6. Codeforces Round #774 (Div. 2)E题题解

    Codeforces Round #774 (Div. 2) E. Power Board 题目陈述 有一个n×m(1≤n,m≤106)n\times m(1\le n,m\le10^6)n×m(1≤ ...

  7. Codeforces Round #702 (Div. 3)全部题解

    题目链接:https://codeforces.com/contest/1490 文章目录 A. Dense Array B. Balanced Remainders C. Sum of Cubes ...

  8. Codeforces Round #640 (Div. 4)(ABCDEG题解)

    文章目录 A. Sum of Round Numbers B - Same Parity Summands C - K-th Not Divisible by n D - Alice, Bob and ...

  9. Codeforces Round #635 (Div. 2)(A~D)题解

    Codeforces #635 A~D A.Ichihime and Triangle B.Kana and Dragon Quest game C.Linova and Kingdom D.Xeni ...

最新文章

  1. zts在c语言中的意思,C语言入门-全局变量 - osc_wna7tzts的个人空间 - OSCHINA - 中文开源技术交流社区...
  2. boost之asio异步io使用实例
  3. 多重循环练习之九九乘法表
  4. 到底逾期几次才会影响贷款申请?
  5. JFinal 1.5 发布,JAVA极速WEB+ORM框架
  6. 实现mysql百度式查询_mysql查询优化建议(百度)
  7. 小鹏汽车回应“非法收集人脸数据被罚10万”:误购第三方设备 数据已删除
  8. android 上下滑动重影
  9. 四边形内接于圆定理_2020中考几何秘籍:初中最全几何定理和解题思路
  10. 谈谈疑似中介规则策略
  11. nodejs实战《一起学 Node.js》 使用 Express + MongoDB 搭建多人博客
  12. 爬虫初窥day1:urllib
  13. VC++如何根据进程名获取进程ID
  14. 软件设计方案说明书的编写
  15. win7 oem key
  16. 计算机组装流程是什么,组装电脑的步骤
  17. vue3 动态获取屏幕尺寸
  18. 深蓝色固体Cyanine5-Azide,Cy5-N3,Cy5 Azide,菁染料CY5叠氮
  19. 2.8 CSS3新特性
  20. 使用计算机室刷卡上机,浅析高校计算机实验室综合信息管理系统

热门文章

  1. UBT14:ubuntu安装Drawing
  2. 火山视窗CEF浏览器用网页框架操作实现取本机IP、地址
  3. puppy linux wifi6,Puppy官网
  4. angular7中使用ckplayer插件实现各大浏览器视频播放功能
  5. 资源管理系统-CKPLayer去除播放窗口水印
  6. 使用超级用户登录系统linux,登录和退出Linux系统
  7. lora物联网解决方案
  8. DaggerXXXComponent找不到问题
  9. 二类电商运营怎么选品 二类电商怎么运营?
  10. web自动化笔记九:验证码的处理方式