Codeforces Round #485 (Div. 2) 部分题解

题目链接

A题:Infinity Gauntlet

解题报告:
直接上 STL map 标记。

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int maxn=1e6+5;
map<string,string >mp;
map<string,bool>MP;
string s[maxn];
queue<string>q;
int main(){
 
    mp["purple"]="Power";
    mp["green"]="Time";
    mp["blue"]="Space";
    mp["orange"]="Soul";
    mp["red"]="Reality";
    mp["yellow"]="Mind";
    int t,ans=0;
    scanf("%d",&t);
    for(int i=1;i<=t;i++){
        cin>>s[i];
        if(mp.count(s[i])) ans++;
        MP[s[i]]=true;
    }
    printf("%d\n",6-ans);
    for(auto it:mp){
        if(!MP.count(it.first)){
            cout<<it.second<<endl;
        }
    }
    return 0;
}

B题 :High School: Become Human

大致题意:给你两个整数 x 和 y 。输出 x^y 与 y^x 得大小关系。

解题报告:
对 x^y 和 y^x 两边去对数 化成 y* logx 与 x*log y 。

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
 
 
using namespace std;
const int maxn=1e6+5;
 
 
int main(){
    double x,y;
    scanf("%lf%lf",&x,&y);
    if(y*log(x)>x*log(y)) printf(">");
    else if(y*log(x)<x*log(y)) printf("<");
    else printf("=");
    return 0;
}

C题:Three displays

大致题意:
给你 n 块 空地,每块空地得大小是 si ,占用该空地得花费是 ci 。
先需占用三块空地满足如下关系 :i<j<k 且 si<sj<sk ,求你求最小花费。
解题报告:
我们可以先求出占用任意满足要求的两块空地的花费,在枚举第三块满足要求的空地。

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
 
using namespace std;
const int maxn=1e6+5;
const int inf=0x3f3f3f3f;
 
int s[maxn],c[maxn];
int dp[maxn],f[maxn];
 
 
int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&s[i]);
    for(int i=1;i<=n;i++) scanf("%d",&c[i]);
    dp[1]=inf;
    for(int i=2;i<=n;i++){
        dp[i]=inf;
        for(int j=i-1;j>=1;j--){
            if(s[i]>s[j]) dp[i]=min(dp[i],c[i]+c[j]);
        }
    }
    int ans=inf;
    for(int i=3;i<=n;i++){
        f[i]=inf;
        for(int j=i-1;j>=2;j--){
            if(s[i]>s[j]) f[i]=min(f[i],c[i]+dp[j]);
        }
        ans=min(ans,f[i]);
    }
    if(ans==inf) printf("-1");
    else printf("%d\n",ans);
    return 0;
 
}

D题:Fair

大致题意:
有 n 个城市,m 条双向道路连接两个城市(边权为 1 ),整个图保证连通。有 k 种物品,但每个城市只有一种,现在它们都需要 s 种物品来举办展览,可以去其他城市获取该城市的物品,花费是两城市之间的最短路径长度。求每个城市举办展览的最小花费。
解题报告:
正向爆搜必TLE,不妨逆向考虑,我们考虑每种物品到各城镇的花费(路径)即以每一种物品为源点进行bfs。
最后对 城镇到各物品的花费进行排序取前 s个。

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
 
struct TMD{
    int to,next;
}edge[maxn<<1];
int n,m,k,s;
int city[maxn],dis[maxn][105];
int head[maxn],cnt;
bool vis[maxn],visited[105];
void add(int from,int to){
    edge[++cnt]={to,head[from]};
    head[from]=cnt;
}
void bfs(int root){
    queue<int>q;
    for(int i=1;i<=n;i++){
        vis[i]=false;
        if(city[i]==root){
            dis[i][root]=0;
            q.push(i);
            vis[i]=true;
        }
    }
    while(!q.empty()){
        int now=q.front();q.pop();
        for(int i=head[now];~i;i=edge[i].next){
            int to=edge[i].to;
            if(vis[to]) continue;
            dis[to][root]=dis[now][root]+1;
            q.push(to);vis[to]=true;
        }
    }
}
int main(){
    mem(head,-1);mem(visited,false);mem(dis,inf);
    int u,v;
    scanf("%d%d%d%d",&n,&m,&k,&s);
    for(int i=1;i<=n;i++) scanf("%d",&city[i]);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        add(u,v);add(v,u);
    }
    for(int i=1;i<=n;i++){
        if(!visited[city[i]]) bfs(city[i]),visited[city[i]]=true;
    }
    for(int i=1;i<=n;i++){
        sort(dis[i]+1,dis[i]+k+1);
        int ans=0;
        for(int j=1;j<=s;j++){
            ans+=dis[i][j];
        }
        printf("%d ",ans);
    }
    return 0;
 
}

E题:Petr and Permutations

大致题意:
给你 一个 1 到 n 任意排列的数组,问你该数组是由 1,2,3…n 排列经过 3*n 还是 7*n+1 次随机交换得来的。
解题报告:
发现 3*n 与 7*n+1 的奇偶性相反。
考虑任意交换两个数对逆序数的影响,先从简单的考虑:交换相邻的两个数 逆序数改变 1;由此推出复杂的交换 x y 位置(x<y),考虑 y 移到 x 逆序数的改变 :y-x 再将 x移到原来y 的位置逆序数改变:y-x-1,故总交换次数 2*(y-x)-1 。
若所给数组的逆序数为奇数说明交换了奇数次,在考虑 3*n 与 7*n+1的奇偶性即可,反之亦然。

#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e6+5;
const int inf=0x3f3f3f3f;

int p[maxn],tree[maxn],n;
int lowbit(int x) {return x&(-x);}
void modify(int x){
    for(int i=x;i<=n;i+=lowbit(i)) tree[i]++;
}
int get(int x){
    int ans=0;
    for(int i=x;i>=1;i-=lowbit(i)) ans+=tree[i];
    return ans;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&p[i]);
    int ans=0;
    for(int i=1;i<=n;i++){
        ans+=i-get(p[i])-1;
        modify(p[i]);
    }
    if(ans&1){
        if((3*n)&1) printf("Petr\n");
        else printf("Um_nik\n");
    }
    else {
        if((3*n)&1) printf("Um_nik\n");
        else printf("Petr\n");
    }
    return 0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值