Codeforces Round #582 (Div. 3)简要题解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_42671946/article/details/100539554

A - Chips Moving

分析:不改变奇偶的情况下是免费的,那么数一下奇数和偶数的个数就可以了。

#include "bits/stdc++.h"
using namespace std;
int main(){
    int n;
    int od=0,ev=0;
    cin>>n;
    int x;
    while(n--){
        cin>>x;
        if(x&1)od++;
        else ev++;
    }
    cout<<min(od,ev)<<endl;
}

B - Bad Prices

分析:记录一个后缀最小值,然后倒着扫一遍就可以了。

#include "bits/stdc++.h"
 
using namespace std;
int a[150004];
 
int main() {
    int t;
    cin >> t;
    while (t--) {
        int n;
        cin >> n;
        for (int i = 1; i <= n; ++i) {
            scanf("%d", &a[i]);
        }
        int ans = 0;
        int mini = 1e9;
        for (int i = n; i >= 1; --i) {
            if(a[i] > mini) ans ++;
            else mini = a[i];
        }
        cout<<ans<<endl;
    }
}

C - Book Reading

分析:简单分析一下可以发现,最终加上去的答案是一个循环节,找到循环节然后计算一下就可以了。

#include "bits/stdc++.h"
 
using namespace std;
int a[150004];
 
int main() {
    int t;
    cin >> t;
    while (t--) {
        long long n,m;
        cin >> n >> m;
        long long now = m;
        long long ans = 0;
        while(now <= n){
            ans += now % 10;
            now += m;
            if(now % 10 == m % 10){
                now -= m;
                break;
            }
        }
        ans = ans * (n / now);
        now = now * (n / now);
        while(now <= n){
            ans += now % 10;
            now += m;
        }
        cout<<ans<<endl;
    }
}

D1 - Equalizing by Division (easy version)&&D2 - Equalizing by Division (hard version)

分析:所有的可能出现的值理论上最多只有nlogn个,那么记录所有值到达这个值的步数,对于个数>=k的去前k个就可以了。

#include "bits/stdc++.h"
 
using namespace std;
int a[200004];
map<int,vector<int>>mp;
int main() {
    int n,k;
    cin>>n>>k;
    for (int i = 1; i <= n; ++i) {
        scanf("%d",&a[i]);
        int temp = a[i];
        int cnt = 0;
        while(temp){
            if(mp.count(temp))mp[temp].push_back(cnt);
            else {
                vector<int>v;
                mp[temp]=v;
                mp[temp].push_back(cnt);
            }
            temp >>= 1;
            cnt ++;
        }
    }
    int ans= 1e9;
    for(auto it : mp){
        if(it.second.size() >= k){
            sort(it.second.begin(),it.second.end());
            int sum = 0;
            for (int i = 0; i < k; ++i) {
                sum += it.second[i];
            }
            ans = min(ans,sum);
        }
    }
    printf("%d\n",ans);
 
}

E - Two Small Strings

分析:总共情况只有那么几种,模拟一下就可以了。

#include "bits/stdc++.h"
 
using namespace std;
bool check(string s,string t){
    for (int i = 0; i + t.size() <= s.size(); ++i) {
        bool ok =1;
        for (int j = i; j < i + t.size(); ++j) {
            if(s[j]!=t[j-i])ok=0;
        }
        if(ok)return 1;
    }
    return 0;
}
int main() {
    int n;
    string s,t;
    cin>>n>>s>>t;
    string ye[6]={"abca","acba","bacb","bcab","cabc","cbac"};
    for (int i = 0; i < 6; ++i) {
        if(!check(ye[i],s) && !check(ye[i],t)){
            ye[i].erase(--ye[i].end());
            puts("YES");
            for (int j = 0; j < n; ++j) {
                cout<<ye[i];
            }
            puts("");
            return 0;
        }
    }
 
    if(t[0]==s[0]){
        puts("YES");
        char t1 = t[1],t2=s[1];
        for (int i = 0; i < n; ++i) {
            putchar(t1);
            putchar(t2);
        }
        for (int i = 0; i < n; ++i) {
            putchar(t[0]);
        }
    }
    else if(t[1] == s[1]){
        puts("YES");
        char t1 = t[0],t2=s[0];
        for (int i = 0; i < n; ++i) {
            putchar(t[1]);
        }
        for (int i = 0; i < n; ++i) {
            putchar(t1);
            putchar(t2);
        }
 
    }
    else if(t[1]==s[0] && s[1] == t[0]){
        puts("YES");
        char temp;
        for (int i = 0; i < 3; ++i) {
            if(i+'a'!=t[1] && i+'a'!=t[0])temp=i+'a';
        }
        for (int i = 0; i < n; ++i) {
            putchar(s[0]);
        }
        for (int i = 0; i < n; ++i) {
            putchar(temp);
        }
        for (int i = 0; i < n; ++i) {
            putchar(s[1]);
        }
 
    }
}

F - Unstable String Sort

分析:就这题稍微有点意思。

我们要求出一个字符串,这个字符串最少有K个字符,同时给出两个1到n的置换p,q,要求对于置换p,q在置换后的字符串是单调非减的。那么我们先默认p置换已经有序了,那么我们只需要求出在这种情况下,置换q也有序就可以了。

首先我们需要找出一个置换t使得置换p置换t后于置换q等效,然后现在对于置换t这个序列,对于i<j有s[i]<=s[j],对于t[i]<t[j]有s[i]<=s[j],那么从t[i]=1的位置开始,如果t[i]=x的位置p前面不存在t[j]>x,并且此时字母已经填到c,那么此时字母可以加1,即d,否则还是c,然后把p前面的还未赋值的位置赋值就可以了。 

然后再根据两个置换pt还原即可。pq写反,WA的惨无人道

#include "bits/stdc++.h"
 
using namespace std;
int p[200004], q[200004];
int tp[200004];
int tp2[200004];
char ans[200004];
char res[200004];
int aaa[200004];
 
int main() {
    int n, k;
    cin >> n >> k;
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &p[i]);
        tp[p[i]] = i;
    }
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &q[i]);
        aaa[i]=q[i];
        q[i] = tp[q[i]];
        tp2[q[i]] = i;
    }
    if(k==1){
        puts("YES");
        for (int i = 0; i < n; ++i) {
            putchar('a');
        }
        return 0;
    }
    char now = 'a' - 1;
    int last = 1;
    int maxi = 0;
    for (int i = 1; i <= n; ++i) {
        int pos = tp2[i];
        if (pos < last)continue;
        if (i > maxi)now++;
        if (now > 'z' ) now--;
        for (int j = last; j <= pos; ++j) {
            ans[j] = now;
            maxi = max(maxi, q[j]);
        }
        last = pos + 1;
    }
    if (ans[n] - 'a' + 1 < k) {
        return 0 * puts("NO");
    }
    for (int i = 1; i <= n; ++i) {
        res[p[q[i]]] = ans[i];
    }
    puts("YES");
    for (int i = 1; i <= n; ++i) {
        putchar(res[i]);
    }
    puts("");
 
}

G - Path Queries

分析:将询问离线,然后按边权大小将点加进去,维护一下每个连通分量的点的个数,每个连通分量的贡献应该是cn2,写个带权并查集就可以了。

#include "bits/stdc++.h"
 
using namespace std;
 
struct edge {
    int u, v, w;
 
    bool friend operator<(edge a, edge b) {
        return a.w < b.w;
    }
} e[200004];
 
int fa[200004];
int num[200004];
 
int Find(int a) {
    if (a == fa[a])return a;
    else return fa[a] = Find(fa[a]);
}
 
pair<int, int> que[200004];
long long ans[200004];
 
int main() {
    int n, m;
    cin >> n >> m;
    int x, y, z;
    for (int i = 0; i <= n; ++i) {
        fa[i] = i;
        num[i] = 1;
    }
    for (int i = 0; i < n - 1; ++i) {
        scanf("%d%d%d", &x, &y, &z);
        e[i] = {x, y, z};
    }
    sort(e, e + n - 1);
    for (int i = 0; i < m; ++i) {
        scanf("%d", &x);
        que[i] = make_pair(x, i);
    }
    sort(que, que + m);
    long long res = 0;
    int pos = 0;
    for (int i = 0; i < m; ++i) {
        while (pos < n - 1 && e[pos].w <= que[i].first) {
            int fx = Find(e[pos].u);
            int fy = Find(e[pos].v);
            res -= 1LL * (num[fx] - 1) * num[fx] / 2;
            res -= 1LL * (num[fy] - 1) * num[fy] / 2;
            res += 1LL * (num[fx] + num[fy] - 1) * (num[fx] + num[fy]) / 2;
            fa[fx] = fy;
            num[fy] += num[fx];
            pos ++;
        }
        ans[que[i].second]=res;
    }
    for (int i = 0; i < m; ++i) {
        printf("%lld ",ans[i]);
    }
}

 

猜你喜欢

转载自blog.csdn.net/qq_42671946/article/details/100539554