Codeforces Round #547题解
A题
先除再计算即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=3e5+10; const int inf=0x3f3f3f3f; int main(){ ios::sync_with_stdio(false); int n,m; cin>>n>>m; int flag=0; int cnt=0; if(m%n){ cout<<-1<<endl; return 0; } n=m/n; while(n%2==0){ n/=2; cnt++; } while(n%3==0){ n/=3; cnt++; } if(n==1){ cout<<cnt<<endl; } else{ cout<<-1<<endl; } return 0; }
B题
因为保证存在一个,因此直接扩大一倍,这样答案肯定在这之间
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=4e5+10; const int inf=0x3f3f3f3f; int a[N]; int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; for(i=1;i<=n;i++) cin>>a[i]; for(i=n+1;i<=2*n;i++){ a[i]=a[i-n]; } int ans=0; int cnt=0; for(i=1;i<=2*n;i++){ if(a[i]==0){ ans=max(ans,cnt); cnt=0; } else{ cnt++; } } cout<<ans<<endl; return 0; }
C题
因为排列是每个都不同,因此用前缀和计算出最大的那个,那个就是n
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=4e5+10; const int inf=0x3f3f3f3f; int p[N]; ll sum; int ans[N],st[N]; int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; int pos=1; int mx=0; for(i=2;i<=n;i++){ cin>>p[i]; sum+=p[i]; if(sum>mx){ sum=mx; pos=i; } } ans[pos]=n; st[n]=1; for(i=pos-1;i>=1;i--){ ans[i]=ans[i+1]-p[i+1]; if(ans[i]<=0||ans[i]>n||st[ans[i]]){ cout<<-1<<endl; return 0; } st[ans[i]]=1; } for(i=pos+1;i<=n;i++){ ans[i]=ans[i-1]+p[i]; if(ans[i]<=0||ans[i]>n||st[ans[i]]){ cout<<-1<<endl; return 0; } st[ans[i]]=1; } for(i=1;i<=n;i++){ cout<<ans[i]<<" "; } cout<<endl; return 0; }
D题
发现每一位是独立的,因此用每一位进行匹配,之后再用多余的?进行匹配
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=4e5+10; const int inf=0x3f3f3f3f; int a[N]; int b[N]; vector<int> num1[27]; vector<int> num2[27]; vector<int> res1,res2; vector<pll> ans; int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i; string s; cin>>s; s=" "+s; for(i=1;i<(int)s.size();i++){ if(s[i]=='?'){ num1[26].push_back(i); } else{ int x=s[i]-'a'; num1[x].push_back(i); } } cin>>s; s=" "+s; for(i=1;i<(int)s.size();i++){ if(s[i]=='?') num2[26].push_back(i); else{ int x=s[i]-'a'; num2[x].push_back(i); } } int cnt=0; for(i=0;i<26;i++){ while((int)num1[i].size()&&(int)num2[i].size()){ int x=num1[i].back(); int y=num2[i].back(); num1[i].pop_back(); num2[i].pop_back(); ans.push_back({x,y}); } while((int)num1[i].size()){ res1.push_back(num1[i].back()); num1[i].pop_back(); } while((int)num2[i].size()){ res2.push_back(num2[i].back()); num2[i].pop_back(); } } for(auto x:res2){ if(num1[26].size()){ ans.push_back({num1[26].back(),x}); num1[26].pop_back(); } } for(auto x:res1){ if(num2[26].size()){ ans.push_back({x,num2[26].back()}); num2[26].pop_back(); } } while((int)num1[26].size()&&(int)num2[26].size()){ int x=num1[26].back(); int y=num2[26].back(); num1[26].pop_back(); num2[26].pop_back(); ans.push_back({x,y}); } cout<<ans.size()<<endl; for(auto x:ans){ cout<<x.first<<" "<<x.second<<endl; } return 0; }
E题
很明显的二分算法,答案的轮数具有单调性,因此枚举每一位,以他结束的答案,之后全部答案取min就是最后答案
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=4e5+10; const int inf=0x3f3f3f3f; ll d[N]; ll sum[N]; ll res[N]; int main(){ ios::sync_with_stdio(false); ll h,n; cin>>h>>n; int i; int flag=0; for(i=1;i<=n;i++){ cin>>d[i]; sum[i]=sum[i-1]+d[i]; if(sum[i]<=-h){ cout<<i<<endl; return 0; } } if(sum[n]>=0){ cout<<-1<<endl; return 0; } ll ans=1e18; for(i=1;i<=n;i++){ ll l=0,r=1e12; while(l<r){ ll mid=l+r>>1; if(1.0*sum[n]<=1.0*(-h-sum[i])/mid){ r=mid; } else{ l=mid+1; } } ans=min(ans,l*n+i); } cout<<ans<<endl; return 0; }
F1题,F2题
只是数据范围的不同,直接拿正解来做,观察到1500,这玩意一看就是n^2做,想了一会,发现每个和都是独立的,因此可以预处理出来所有区间的和,之后对每个和单独讨论
这一步想到了后面就简单了。后面就是在一些区间内找到不覆盖的最多的区间个数,经典贪心套路,按照右端点排序之后,遇到合适的就放进来
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=2e6+10; const int inf=0x3f3f3f3f; ll sum[N]; int a[N]; vector<pll> g[N]; vector<int> num; int find(int x){ return lower_bound(num.begin(),num.end(),x)-num.begin()+1; } bool cmp(pll a,pll b){ return a.second<b.second; } int main(){ ios::sync_with_stdio(false); int n; cin>>n; int i,j; for(i=1;i<=n;i++){ cin>>a[i]; sum[i]=sum[i-1]+a[i]; } int ans=0; for(i=1;i<=n;i++){ for(j=0;j<i;j++){ int x=sum[i]-sum[j]; num.push_back(x); } } sort(num.begin(),num.end()); num.erase(unique(num.begin(),num.end()),num.end()); for(i=1;i<=n;i++){ for(j=0;j<i;j++){ int x=sum[i]-sum[j]; int pos=find(x); g[pos].push_back({j+1,i}); } } int id=0; for(i=1;i<=(int)num.size();i++){ if(!(int)g[i].size()) continue; sort(g[i].begin(),g[i].end(),cmp); int cnt=1; int tmp=0; for(j=1;j<(int)g[i].size();j++){ if(g[i][j].first>g[i][tmp].second){ cnt++; tmp=j; } } if(cnt>ans){ ans=cnt; id=i; } } cout<<ans<<endl; cout<<g[id][0].first<<" "<<g[id][0].second<<endl; int tmp=0; for(j=1;j<(int)g[id].size();j++){ if(g[id][j].first>g[id][tmp].second){ cout<<g[id][j].first<<" "<<g[id][j].second<<endl; tmp=j; } } return 0; }
G题
这题贪心过于套路,看出来其实就是跟度数相关,因为每个点连的边要满足条件,并且每个点只有一个父亲,因此父亲点周围的边其实不影响儿子,因此答案就是第k+1大的度数
而方案就dfs构造一下就行,主要关注你的父亲是啥,记得判断一下。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pll; typedef pair<int,int> plll; const int N=2e6+10; const int inf=0x3f3f3f3f; int h[N],ne[N],e[N],idx; int w[N],in[N]; int mx; int ans[N]; void add(int a,int b,int c){ e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++; } void dfs(int u,int fa,int x){ int cnt=1; if(cnt==x&&cnt<mx) cnt++; for(int i=h[u];i!=-1;i=ne[i]){ int j=e[i]; if(j==fa) continue; ans[w[i]]=cnt; dfs(j,u,cnt); if(cnt<mx) cnt++; if(cnt==x&&cnt<mx) cnt++; } } int main(){ ios::sync_with_stdio(false); memset(h,-1,sizeof h); int i; int n,k; cin>>n>>k; for(i=1;i<n;i++){ int a,b; cin>>a>>b; add(a,b,i); add(b,a,i); in[a]++; in[b]++; } sort(in+1,in+1+n); reverse(in+1,in+1+n); mx=in[k+1]; dfs(1,-1,0); cout<<mx<<endl; for(i=1;i<n;i++) cout<<ans[i]<<" "; cout<<endl; return 0; }
没有人不辛苦,只有人不喊疼