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;
}
View Code

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;
}
View Code

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;
}
View Code

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;
}
View Code

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;
}
View Code

 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;
}
View Code

 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;
}
View Code

 

posted @ 2020-12-25 22:16  朝暮不思  阅读(84)  评论(0编辑  收藏  举报