Codeforces Round #702 题解
A题
找两两比列,按2的次幂进行划分
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int N=1e5+200; const int mod=1e9+7; int a[N]; int main(){ ios::sync_with_stdio(false); int t; cin>>t; while(t--){ int n; cin>>n; int i; for(i=1;i<=n;i++){ cin>>a[i]; } int ans=0; for(i=1;i<n;i++){ int x=max(a[i],a[i+1]); int y=min(a[i],a[i+1]); int d=x/y; if(x%y) d++; int tmp=0; for(int j=1;j<10;j++){ if(pow(2,j)<d){ tmp++; } else{ break; } } ans+=tmp; } cout<<ans<<endl; } return 0; }
B题
暴力做,我们发现每个位置的数相同,因此模拟增量,从mod 0开始计算差值,之后进行平移
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int N=1e5+200; const int mod=1e9+7; int a[N]; int cnt[5]; int main(){ ios::sync_with_stdio(false); int t; cin>>t; while(t--){ int n; cin>>n; int i; for(i=1;i<=n;i++){ cin>>a[i]; } for(i=0;i<3;i++) cnt[i]=0; for(i=1;i<=n;i++){ if(a[i]%3==0) cnt[0]++; if(a[i]%3==1) cnt[1]++; if(a[i]%3==2) cnt[2]++; } int x=n/3; int ans=0; if(cnt[0]<x){ cnt[2]-=(x-cnt[0]); ans+=(x-cnt[0]); } else{ cnt[1]+=(cnt[0]-x); ans+=(cnt[0]-x); } if(cnt[1]<x){ ans+=(x-cnt[1])*2; } else{ ans+=(cnt[1]-x); } cout<<ans<<endl; } return 0; }
C题
模拟题,因为开三次方的大小不会太大,因此枚举每个平方数计算
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int N=1e5+200; const int mod=1e9+7; ll a[N]; map<ll,int> m1; int main(){ ios::sync_with_stdio(false); int t; cin>>t; for(ll i=1;i<=10000;i++){ a[i]=i*i*i; m1[a[i]]++; } while(t--){ ll x; cin>>x; int flag=0; for(int i=1;i<=10000;i++){ if(m1[x-a[i]]){ flag=1; break; } } if(flag){ cout<<"YES"<<endl; } else{ cout<<"NO"<<endl; } } return 0; }
D题
模拟建树,01位置分别代表左右子树,log跳跃,记录每个位置的pos,从根节点开始,根据相对位置跳转
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int N=1e5+200; const int mod=1e9+7; int a[N]; int g[200][200]; int pos[N],depth[N]; void dfs(int u,int fa){ depth[u]=depth[fa]+1; for(int i=0;i<=1;i++){ int j=g[u][i]; if(j==0) continue; dfs(j,u); } } int main(){ ios::sync_with_stdio(false); int t; cin>>t; while(t--){ int n; cin>>n; int i; for(i=1;i<=n;i++){ cin>>a[i]; pos[a[i]]=i; g[i][0]=g[i][1]=0; } int rt=n; depth[rt]=1; for(i=n-1;i>=1;i--){ int tmp=rt; while(1){ if(pos[i]<pos[tmp]){ if(g[tmp][0]){ tmp=g[tmp][0]; } else{ g[tmp][0]=i; break; } } else{ if(g[tmp][1]){ tmp=g[tmp][1]; } else{ g[tmp][1]=i; break; } } } } dfs(rt,0); for(i=1;i<=n;i++){ cout<<depth[a[i]]-1<<" "; } cout<<endl; } return 0; }
E题
对于一个人最优解就是把比他小的全吃完再往后比,因此记录一个前缀和,找到最后一个前缀和不能大于后一个数的位置,后面的大小都可以
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int N=2e5+200; const int mod=1e9+7; int a[N],b[N]; map<int,int> m1; int sign[N]; int main(){ ios::sync_with_stdio(false); int t; cin>>t; while(t--){ int n; cin>>n; int i; m1.clear(); for(i=1;i<=n;i++){ cin>>a[i]; sign[i]=0; b[i]=a[i]; } sort(a+1,a+1+n); ll sum=0; for(i=1;i<n;i++){ sum+=a[i]; if(sum<a[i+1]){ sign[i]=1; } } for(i=n;i>=1;i--){ if(sign[i]) break; m1[a[i]]=1; } cout<<n-i<<endl; for(i=1;i<=n;i++){ if(m1[b[i]]){ cout<<i<<" "; } } cout<<endl; } return 0; }
F题
类似差分数组的思想,维护前缀后缀,这样枚举C,前面的变成0,后面的变成C即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int N=2e5+200; const int mod=1e9+7; int a[N]; ll pre[N],suf[N],d[N]; map<ll,int> m1; int main(){ ios::sync_with_stdio(false); int t; cin>>t; while(t--){ int n; cin>>n; int i; m1.clear(); for(i=1;i<=n;i++){ cin>>a[i]; m1[a[i]]++; pre[i]=suf[i]=d[i]=0; } suf[n+1]=0; d[n+1]=0; int cnt=0; for(auto x:m1){ pre[x.second]+=x.second; suf[x.second]+=x.second; d[x.second]+=1; } for(i=1;i<=n;i++){ pre[i]+=pre[i-1]; } for(i=n;i>=1;i--){ suf[i]+=suf[i+1]; } for(i=n;i>=1;i--){ d[i]+=d[i+1]; } ll ans=1e9; for(i=1;i<=n;i++){ //cout<<pre[i-1]<<" "<<suf[i+1]<<" "<<d[i]*i<<endl; ans=min(ans,pre[i-1]+suf[i+1]-d[i+1]*i); } cout<<ans<<endl; } return 0; }
G题
一大圈的贡献是相等的,用map的lower_bound进行二分查找分类讨论即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<ll,ll> pll; const int N=2e5+200; const int mod=1e9+7; ll a[N]; map<ll,ll> m1; int main(){ ios::sync_with_stdio(false); int t; cin>>t; while(t--){ ll n,m; cin>>n>>m; m1.clear(); int i; ll row=0,mx=0,mxid=0; for(i=1;i<=n;i++){ cin>>a[i]; row+=a[i]; if(row>mx){ mx=row; mxid=i; m1[mx]=i; } } for(i=1;i<=m;i++){ ll x; cin>>x; auto it=m1.lower_bound(x); if(it==m1.end()&&row<=0){ cout<<-1<<" "; continue; } else if(it==m1.end()){ auto lst=m1.end(); --lst; int nd=(x-lst->first+row-1)/row; it=m1.lower_bound(x-nd*row); cout<<it->second+nd*n-1<<" "; } else{ cout<<it->second-1<<" "; } } cout<<endl; } return 0; }
没有人不辛苦,只有人不喊疼