Codeforces Round 547 (Div. 3)


layout: post
title: Codeforces Round 547 (Div. 3)
author: "luowentaoaa"
catalog: true
tags:
mathjax: true
- codeforces


传送门

E - Superhero Battle (数学)

思路

首先分为情况

如果在第一轮内就打死

或者如果一整轮的伤害大于等于0那一轮相当于白费

如果小于0那就说明肯定可以把怪物打死

所以我们就枚举在第K论之后的哪一回合打死即可

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+50;
typedef long long ll;

ll H,n;
ll d[maxn];
ll mx=2e18+50;
ll s[maxn];
int main(){

    std::ios::sync_with_stdio(false);
    cin>>H>>n;
    ll sum=0;
    for(ll i=1;i<=n;i++)cin>>d[i],sum+=d[i],s[i]=s[i-1]+d[i];

    for(ll i=1;i<=n;i++){
        if(-s[i]>=H)mx=min(mx,i);
    }
    if(sum<0){
        for(ll i=1;i<=n;i++){
            ll now=sum+s[i];
            now=-now;
            //cout<<"i="<<i<<" now="<<now<<endl;
            if(now>=H)mx=min(mx,i+n);
            else{
                ll ned=-sum;
                ll HH=H;
                HH-=now;
                ll time=HH/ned;
                if(HH%ned)time++;

                mx=min(mx,time*n+i+n);
            }
        }
    }
    if(mx==2e18+50)cout<<-1<<endl;
    else
        cout<<mx<<endl;
    return 0;
}
/*
1000000000000
4999999999996
*/

F2 - Same Sum Blocks (Hard) (贪心)

思路

首先枚举右端点 同时枚举左端点如果对于这一区间的权值保存的右端点比左端点还大那就加入他,同时更新答案

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+50;
typedef long long ll;

map<int,pair<int,int> >mp;

///区间和,次数,最后一次右边界
int sum[1550],a[1550];
vector<int>G;
struct node{
    int num;
    int R;
    vector<pair<int,int> >ve;
}my[1500*1500/2+50];
int id(int x){
    return lower_bound(G.begin(),G.end(),x)-G.begin();
}
int main(){

    std::ios::sync_with_stdio(false);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>a[i],sum[i]=sum[i-1]+a[i];

    for(int i=1;i<=n;i++){
        int sum=0;
        for(int j=i;j<=n;j++){
            sum+=a[j];
            G.push_back(sum);
        }
    }
    sort(G.begin(),G.end());
    G.erase(unique(G.begin(),G.end()),G.end());

    for(int i=1;i<=n;i++){
        for(int j=1;j<=i;j++){
            int s=sum[i]-sum[j-1];
            s=id(s);
            if(j>my[s].R){
                my[s].R=i;
                my[s].num++;
                my[s].ve.push_back({j,i});
            }
        }
    }
    int ans=0,p;
    for(int i=0;i<G.size();i++){
        if(my[i].num>ans){
            ans=my[i].num;
            p=i;
        }
    }
    cout<<ans<<endl;
    for(auto i:my[p].ve){
        cout<<i.first<<" "<<i.second<<endl;
    }

    return 0;
}

G - Privatization of Roads in Treeland (树)

思路

首先答案肯定是第k+1大的度数

然后就是构造这个树了,我们需要一个可以让颜色不重复的方案,那我们就直接bfs下去就行

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+50;
int n,k;
#define bug cout<<"he"<<endl;
int ind[maxn];

int Next[maxn<<1],Laxt[maxn],To[maxn<<1],cnt;
int edge[maxn],road[maxn<<1],id[maxn<<1];

void add(int u,int v,int i){
    Next[++cnt]=Laxt[u];Laxt[u]=cnt;To[cnt]=v,id[cnt]=i;
}

int maxdu;

void bfs(){
    queue<int>Q;
    Q.push(1);
    memset(edge,-1,sizeof(edge));
    edge[1]=-1;
    while(!Q.empty()){
        int now=Q.front();
        Q.pop();
        int kk=edge[now];
        for(int i=Laxt[now];i;i=Next[i]){
            if(edge[To[i]]!=-1||To[i]==1)continue;
            edge[To[i]]=road[id[i]]=(++kk)%maxdu;
           // cout<<"id="<<id[i]<<endl;
            Q.push(To[i]);
        }
    }
}

int main(){
    cin>>n>>k;
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        add(u,v,i);
        add(v,u,i);
        ind[u]++;ind[v]++;
    }
    sort(ind+1,ind+1+n,greater<int>());
    maxdu=ind[k+1];
    cout<<maxdu<<endl;
    bfs();
    for(int i=1;i<n;i++){
        cout<<road[i]+1<<" ";
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/luowentao/p/10569135.html