Codeforces Round #592 (Div. 2) 补题记录

C

  • 题意: n场比赛,总共p分,w为胜利一场的得分,d为平局的得分,求胜利,平局,失败的场数
  • 思路: 因为d次胜利与w次平局所得的分是一样的,假如平局次数超过w次则可以将其转换成d次胜利(w>d所以一定可以转化),枚举到1e5就行了...

D

  • 题意: 树上染色,共有三种颜色且所有相邻三个点颜色不能重复,每个点染不同颜色有不同的值,求最小值且合法的染色方案
  • 思路: 首先树必须是条链,然后枚举前三个点的全排列就可以确定后面点的颜色,求最小值即可(写了个dp调了我半小时QAQ).
#include<bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 1e5+10;

int n;
vector<int> cost[3];
vector<vector<int> > adj;
vector<int> p,perm ={0,1,2},best_perm,ans;
int main(){
    ios::sync_with_stdio(0);cin.tie(0);
    int u,v,root;
    cin >> n;
    for(int i=0;i<3;++i){
        cost[i].resize(n);
        for(int j=0;j<n;++j)    cin >> cost[i][j];
    }
    adj.assign(n,{});
    for(int i=0;i<n-1;++i){
        cin >> u >> v;
        u--;    v--;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    for(int i=0;i<n;++i){
        if(adj[i].size()>2){
            cout <<"-1\n";
            return 0;
        }else if(adj[i].size()==1){
            root = i;
        }
    }
    p.push_back(root);
    while(p.size()<n){
        v = p.back();
        for(auto nx:adj[v]){
            if(p.size()==1 ||  nx != p[p.size()-2]){
                p.push_back(nx);
                break;
            }
        }
    }
    ll best = 1LL<<62;
    do{
        ll score = 0;
        for(int i=0;i<n;++i)    score += cost[perm[i%3]][p[i]];
        if(score<best){
            best_perm = perm;
            best = score;
        }
    }while(next_permutation(perm.begin(),perm.end()));
    cout << best << '\n';
    ans.resize(n);
    for(int i=0;i<n;++i)    ans[p[i]] = best_perm[i%3];
    for(int i=0;i<n;++i)    cout << ans[i]+1<<' ';
    cout <<'\n';
    return 0;
}

E

  • 题意: 一个序列,每次可以选一个数+1或-1,可以操作k次,求最小化最大减最小的差.
  • 思路: 二分差,肯定有一个a[i]是不变的,check时就枚举a[i]不变(上界下界枚举两次),然后lower_bound找到比下界小的,要加到下界,upper_bound找到比上界大的,要减到上界,算操作次数是否满足小于k.
#include<bits/stdc++.h>
using namespace std;
#define ll long long
 
const int N = 1e5+10;
 
ll n,k;
ll a[N],sum[N];
 
bool check(int d){
    for(int i=1;i<=n;++i){
        int low = lower_bound(a+1,a+1+n,a[i])-a-1;
        int hgh = upper_bound(a+1,a+1+n,a[i]+d)-a;
        ll tot = 1LL*low*a[i] - sum[low] + sum[n] - sum[hgh-1] - 1LL*(n-hgh+1)*(a[i]+d);
        if(tot <=k) return true;
    }
    for(int i=1;i<=n;++i){
        int hgh = upper_bound(a+1,a+1+n,a[i])-a;
        int low = lower_bound(a+1,a+1+n,a[i]-d)-a-1;
        ll tot = 1LL*low*(a[i]-d) - sum[low] + sum[n] - sum[hgh-1] - 1LL*(n-hgh+1)*a[i];
        if(tot <=k) return true;
    }
    return false;
}
int main(){
    cin >> n >> k;
    for(int i=1;i<=n;++i) cin >> a[i];
    sort(a+1,a+1+n);
    for(int i=1;i<=n;++i)   sum[i] = sum[i-1] + a[i];
    int l = 0,r = 1e9;
    int mid,ans = -1;
    while(l<=r){
        mid = (l+r)>>1;
        if(check(mid)){
            ans = mid;
            r = mid-1;
        }else{
            l = mid+1;
        }
    }
    cout << ans << endl;
    return 0;
}

这几天训练莫得动力,再不加大力度自己要莫得了

猜你喜欢

转载自www.cnblogs.com/xxrlz/p/11682009.html