Dashboard - Codeforces Round #702 (Div. 3) - Codeforces

Dashboard - Codeforces Round #702 (Div. 3) - Codeforces

1.Problem - A - Codeforces

题意 :就是两个相邻的数字的最大值最大是最小值的两倍,如果超过就只能再两个数字中间插数。问你最少需要多少步使数组成立

思路 :考虑如果一个max(a[i],a[i+1])如果是min(a[i],a[i+1])的两个倍以上那我就考虑把在中间插一个最大值的一半。这样所用的步数肯定是最少的。如果是奇数不能只除以2,还得加上1.

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define fhl(i,x,y) for(int i=x;i>=y;i--)
#define inf 0x3fffffff
#define ll long long
#define pb push_back
#define endl "\n"
int n;
int a[100];
void slove(){
cin>>n;
fel(i,1,n){
cin>>a[i];
}
int ans=0;
for(int i=1;i<n;i++){
int t1=max(a[i],a[i+1]);
int t2=min(a[i],a[i+1]);
while(t1>t2*2){
t1=(t1/2)+(t1%2>0);
ans++;
}
}
cout<<ans<<endl;
}
int main(){
int t;
cin>>t;
while(t--){
slove();
}
return 0;
}

##

2.Problem - B - Codeforces

题意 :题意是能不能使数组中取模三后,余数为0,1,2的数的个数都是相同的,然后可以让ai=ai+1,问你最少需要多少步使得满足条件。

思路 :那我肯定考虑每次都从最近的变过来,0从2来,1从0来,2从1来。这样考虑和你从最多的转移过来本质上是一样的。(比如余数为1的最多,你让他变成0,和先让他变成2,再变成0。都是需要两步)。

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define fhl(i,x,y) for(int i=x;i>=y;i--)
#define inf 0x3fffffff
#define ll long long
#define pb push_back
#define endl "\n"
const int N=3e4+100;
int n;
int a[N];
int vis[3];
void slove(){
memset(vis,0,sizeof(vis));
cin>>n;
fel(i,1,n){
cin>>a[i];
vis[a[i]%3]++;
}
int ans=0;
while(1){
int cnt=0;
for(int i=0;i<3;i++){
if(vis[i]==n/3){
cnt++;
}
}
//cout<<"Hdjksadkjas"<<endl;
if(cnt==3) break;
for(int i=0;i<3;i++){
if(vis[i]<n/3){
int t=n/3-vis[i];
vis[(i-1+3)%3]-=t;
ans+=t;
vis[i]=n/3;
}
}
}
cout<<ans<<endl;
}
int main(){
IOS
int t;
cin>>t;
while(t--){
slove();
}
return 0;
}

 

3.Problem - C - Codeforces

题意 :就是问你一个数能不能拆成其他两个数的三次方之和。数据范围是10^12。

思路 :先预处理好3次方数,那3次方就只有一万个。那我直接考虑先确定一个,然后直接二分查找另外一个就好。

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fel(i,x,y) for(int i=x;i<=y;ihttps://codeforces.com/contest/1490/problem/D
#define fhl(i,x,y) for(int i=x;i>=y;i--)
#define inf 0x3fffffff
#define ll long long
#define pb push_back
#define endl "\n"
#define int long long
const int N=1e4+100;
int a[N],n;
void slove(){
cin>>n;
for(int i=1;i<=10000;i++){
if(a[i]<n){
int t=lower_bound(a+1,a+1+10000,n-a[i])-a;
if(a[t]+a[i]==n){
cout<<"YES"<<endl;
return;
}
}
else break;
}
cout<<"NO"<<endl;
}
signed main(){
for(int i=1;i<=10000;i++){
a[i]=pow(i,3);
//cout<<a[i]<<endl;
}
IOS
int t;
cin>>t;
while(t--){
slove();
}
return 0;
}

 

4.Problem - D - Codeforces

题意 :就是每次找一个最大值,数组左边的建左子树,右边的建右子树。然后输出每一点的深度。

思路 :简单递归一下就好了。每次找到建树范围内的最大值,左右分别递归,然后每次递归深度加1就好。

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define fhl(i,x,y) for(int i=x;i>=y;i--)
#define inf 0x3fffffff
#define ll long long
#define pb push_back
#define endl "\n"
int n;
int a[110];
int ans[110];
void dfs(int l,int r,int step){
if(l<1||r>n||l>r){
return;
}
int mx=l;
for(int i=l;i<=r;i++){
if(a[i]>a[mx]){
mx=i;
}
}
ans[mx]=step;
dfs(l,mx-1,step+1);
dfs(mx+1,r,step+1);
}
void slove(){
cin>>n;
fel(i,1,n){
cin>>a[i];
}
dfs(1,n,0);
for(int i=1;i<=n;i++){
cout<<ans[i]<<" ";
}
cout<<endl;
}
int main(){
IOS
int t;
cin>>t;
while(t--){
slove();
}
return 0;
}

5.Problem - E - Codeforces

题意 :就是有n个人比赛,a[i]大的人赢,有没有可能最后只剩一个人

思路 :就是考虑先对a数组排序,然后求前缀和sum,再从n-1开始往前遍历,看是否sum[i]>=a[i+1].w,如果不行了就break。为什么从后往前遍历呢?这是因为当我遍历到当前点的同时后面点都是可以被解决的(如果不能被解决早就break了)。

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define fhl(i,x,y) for(int i=x;i>=y;i--)
#define inf 0x3fffffff
#define ll long long
#define pb push_back
#define endl "\n"
#define int long long
//想法就是简单的前缀和
const int N=2e5+100;
int n,sum[N];
struct node{
int id,w;
}a[N];
bool cmp(node a,node b){
return a.w<b.w;
}
void slove(){
memset(sum,0,sizeof(sum));
cin>>n;
fel(i,1,n){
cin>>a[i].w;
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+a[i].w;
}
vector<int>ans;
for(int i=n-1;i>=1;i--){//逆序枚举
if(sum[i]>=a[i+1].w){
ans.pb(a[i].id);
}
else break;//因为你前缀和都比这个点少了,肯定就没有点能赢了
}
ans.pb(a[n].id);
sort(ans.begin(),ans.end());
cout<<ans.size()<<endl;
for(auto i:ans){
cout<<i<<" ";
}
cout<<endl;

}
signed main(){
IOS
int t;
cin>>t;
while(t--){
slove();
}
return 0;
}

 

6.Problem - F - Codeforces

题意:使一个数组中每个数出现的次数使相等的,你每次操作可删掉数中的一个数。

思路:就是先用一个map存下每个数的出现次数,然后再用一个map把出现次数相同的归为一类。然后考虑从出现个数分类,遍历第二个map,如果出现次数少于他,就全减去,否则就只减去部分元素,最后相等就好了。具体看代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define fhl(i,x,y) for(int i=x;i>=y;i--)
#define inf 0x3fffffff
#define ll long long
#define pb push_back
#define endl "\n"
#define int long long
//出现次数相同的归为一类,最后那个类最多,就选择他作为基准
const int  N=2e5+100;
unordered_map<int,int>mp,ans;
int n;
int a[N];
struct node {
   int w,x;//出现为w次的元素最后总共有x*w个
};
void slove()
{
   mp.clear();
   ans.clear();
   cin>>n;
   fel(i,1,n) {
       cin>>a[i];
       mp[a[i]]++;//记录每个元素出现的次数
  }
   for(auto[x,y]:mp) {
       ans[y]++;//把出现次数相同的归为一类
  }
   int res=1e18;
   for(auto[x,y]:ans){
  int cnt=0;
  for(auto [z,m]:ans){
  if(z<x){//少的情况
  cnt+=z*m;
}
else if(z>x){//多的情况
cnt+=(z-x)*m;
}
}
res=min(cnt,res);
}
cout<<res<<endl;
}
signed main()
{
   IOS
   int t;
   cin>>t;
   while(t--) {
       slove();
  }
   return 0;
}

 

7.Problem - G - Codeforces

题意:就是有一个数组,每次遍历到这个点可以加上这个点的值。如果循环到末尾了就回到开头。然后有m此询问,问否可以循环遍历这个数组最后的值是这个。最总输出移动的步数,如果不能达到这个值的话就输出-1.最初位置是在a[1]上

思路:这么个数据范围肯定是要考虑用前缀和优化,mx[i]表示1-i前缀和的最大值。,a数组表示前缀和。分情况讨论。

1.如果存在x>mx[n]的同时,a[n]<=0,那很多明显每一轮的值都不会增加了,所以就输出-1

2.如果存在mx[n]>x,那只要一轮就够了,然后就二分查找最大值出现的最早出现的位置就好了。

3.如果每一轮的的前缀和使大于0的那每一轮最大值还可以增加,那你x>mx[n]也无所谓了,我考虑你先减去一个前缀和的最大值(留给最后一轮)。然后看剩余值需要几轮。

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define fel(i,x,y) for(int i=x;i<=y;i++)
#define fhl(i,x,y) for(int i=x;i>=y;i--)
#define inf 0x3fffffff
#define ll long long
#define pb push_back
#define endl "\n"
#define int long long
const int  N=2e5+100;
int n,m;
int a[N];
int mx[N];
void slove(){
memset(mx,0,sizeof(mx));
cin>>n>>m;
fel(i,1,n){
cin>>a[i];
a[i]+=a[i-1];
mx[i]=max(a[i],mx[i-1]);//这个用来记录前缀和的最值
}
for(int i=1,x;i<=m;i++){
cin>>x;
if(mx[n]<x&&a[n]<=0){
cout<<-1<<" ";
}
else if(mx[n]>=x){
cout<<lower_bound(mx+1,mx+1+n,x)-mx-1<<" ";
}
else{
ll ans=ceil((1.0)*(x-mx[n])/a[n]);
x-=ans*a[n];
ans=ans*n-1;
ans+=lower_bound(mx+1,mx+1+n,x)-mx;
cout<<ans<<" ";
}
}
cout<<endl;
}
signed main()
{
   IOS
   int t;
   cin>>t;
   while(t--) {
       slove();
  }
   return 0;
}
 

 

posted @ 2022-08-06 11:20  silky__player  阅读(31)  评论(0)    收藏  举报