codeforces round379(div2)简易题解

Problem A

这是一个sb题,统计一下比较哪个多就好了

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
char str[200050];
int main(void)
{
    int n;
    while(~scanf("%d",&n)){
        scanf("%s",str);
        int l=0;
        for(int i=0;i<n;i++){
            if(str[i]=='A')l++;
        }
        if(l<n-l)puts("Danik");
        else if(l>n-l)puts("Anton");
        else puts("Friendship");
    }
    return 0;
}
Problem B

很明显2先组成256是最优的,然后剩下的用来组成32

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
int main(void)
{
    LL k2,k3,k5,k6;
    while(~scanf("%lld%lld%lld%lld",&k2,&k3,&k5,&k6)){
        LL sum=0;
        LL nm=min(k2,min(k5,k6));
        sum+=nm*(LL)256;
        k2-=nm;
        nm=min(k2,k3);
        sum+=nm*(LL)32;
        printf("%lld\n",sum);
    }
    return 0;
}
Problem C

因为第二种技能保证魔法值使用越多,威力越大,那么只需要枚举第一种技能,根据剩余的魔法值二分第二种技能的使用,答案取最小值即可

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
struct spell{
    LL atk,cost;
}a[200050],b[200050];
int cmp(spell a,spell b){
    return a.cost<b.cost;
}
int main(void)
{
    LL n,m,k;
    while(~scanf("%lld%lld%lld",&n,&m,&k)){
        LL x,s;
        scanf("%lld%lld",&x,&s);
        LL ans=n*x;
        a[0].atk=x;
        a[0].cost=0;
        for(int i=1;i<=m;i++){
            scanf("%lld",&a[i].atk);
        }
        for(int i=1;i<=m;i++){
            scanf("%lld",&a[i].cost);
        }
        for(int i=1;i<=k;i++){
            scanf("%lld",&b[i].atk);
        }
        for(int i=1;i<=k;i++){
            scanf("%lld",&b[i].cost);
        }
        sort(a+1,a+1+m,cmp);
        for(int i=0;i<=m;i++){
            if(a[i].cost>s)break;
            int tar=s-a[i].cost;
            int l=1,r=k;
            LL mx=0;
            while(l<=r){
                int mid=(l+r)>>1;
                if(b[mid].cost<=tar){
                    mx=max(mx,b[mid].atk);
                    l=mid+1;
                }
                else r=mid-1;
            }
            if(n-mx<=0)ans=0;
            else ans=min(ans,(LL)(n-mx)*a[i].atk);

        }
        printf("%lld\n",ans);
    }
    return 0;
}
Problem D

因为不能leap,所以说八个方向能够check的棋子只取决于距king最近的一个,判一下即可

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;

struct node{
    char op;
    int x,y;
    node(){}
    node(char a,int b,int c){op=a,x=b,y=c;}
};
vector<node>lr,rl,r,c;
int cmp(node a,node b){
if(a.x!=b.x)return a.x<b.x;
return a.y<b.y;
}
int main(void)
{
    int n;
    scanf("%d",&n);
    int x,y;
    scanf("%d%d",&x,&y);
    for(int i=1;i<=n;i++){
        char str[2];
        int xx,yy;
        scanf("%s %d %d",str,&xx,&yy);
        node p(str[0],xx,yy);
        if(xx==x)r.push_back(p);
        if(yy==y)c.push_back(p);
        if(xx+yy==x+y)lr.push_back(p);
        if(yy-xx==y-x)rl.push_back(p);
    }
    sort(r.begin(),r.end(),cmp);
    sort(c.begin(),c.end(),cmp);
    sort(rl.begin(),rl.end(),cmp);
    sort(lr.begin(),lr.end(),cmp);
    int flag=0;
    int fl=-1,fr=r.size()+1;
    for(int i=0;i<r.size();i++){
        if(r[i].y<y)fl=i;
        if(r[i].y>y){fr=i;break;}
    }
    if(fl!=-1)if(r[fl].op=='R'||r[fl].op=='Q')flag=1;
    if(fr!=r.size()+1)if(r[fr].op=='R'||r[fr].op=='Q')flag=1;

    fl=-1,fr=c.size()+1;
    for(int i=0;i<c.size();i++){
        if(c[i].x<x)fl=i;
        if(c[i].x>x){fr=i;break;}
    }
    if(fl!=-1)if(c[fl].op=='R'||c[fl].op=='Q')flag=1;
    if(fr!=c.size()+1)if(c[fr].op=='R'||c[fr].op=='Q')flag=1;

    fl=-1,fr=rl.size()+1;
    for(int i=0;i<rl.size();i++){
        if(rl[i].y<y)fl=i;
        if(rl[i].y>y){fr=i;break;}
    }
    if(fl!=-1)if(rl[fl].op=='B'||rl[fl].op=='Q')flag=1;
    if(fr!=rl.size()+1)if(rl[fr].op=='B'||rl[fr].op=='Q')flag=1;

    fl=-1,fr=lr.size()+1;
    for(int i=0;i<lr.size();i++){
        if(lr[i].x<x)fl=i;
        if(lr[i].x>x){fr=i;break;}
    }
    if(fl!=-1)if(lr[fl].op=='B'||lr[fl].op=='Q')flag=1;
    if(fr!=lr.size()+1)if(lr[fr].op=='B'||lr[fr].op=='Q')flag=1;
    if(flag)puts("YES");
    else puts("NO");
    return 0;
}
Problem E

一个联通块内能够同时染色,所以先将联通块缩点,重建后的树保证相邻的两个点颜色不同,考虑以某个点为根,则需要染色的次数为距离它最远的点距离他的距离,设树的直径为 r ,那么ans=(r+1)/2

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
int fa[200050];
int co[200050];
int co2[200050];
int vis[200050];
struct edge{
    int v,nxt;
}e[400050];
int h[200050];
int siz;
struct ed{
    int u,v;
}pre[200050];
void init(){
    siz=0;
    memset(e,-1,sizeof(e));
    memset(h,-1,sizeof(h));
}
void add(int u,int v){
    e[siz].nxt=h[u];
    e[siz].v=v;
    h[u]=siz++;
}
int as=0;
int dfs(int u,int pr){
    int h1=0,h2=0;
    for(int i=h[u];~i;i=e[i].nxt){
        int v=e[i].v;
        if(v!=pr){
            int h=dfs(v,u)+1;
            if(h>h1)h2=h1,h1=h;
            else if(h>h2)h2=h;
        }
    }
    as=max(as,h1+h2);
    return h1;
}
int main(void)
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%d",&co[i]);
    }
    init();
    for(int i=1;i<n;i++){
        int u,v;
        scanf("%d%d",&pre[i].u,&pre[i].v);
        add(pre[i].u,pre[i].v);
        add(pre[i].v,pre[i].u);
    }
    queue<int>mq;
    int cnt=1;
    fa[1]=1;
    co2[1]=co[1];
    vis[1]=1;
    mq.push(1);
    while(!mq.empty()){
        int u=mq.front();
        mq.pop();
        for(int i=h[u];~i;i=e[i].nxt){
            int v=e[i].v;
            if(!vis[v]){
                vis[v]=1;
                if(co[v]==co[u]){
                    fa[v]=fa[u];
                }
                else {
                    fa[v]=++cnt;
                    co2[cnt]=co[v];
                }
                mq.push(v);
            }
        }
    }
    init();
    for(int i=1;i<n;i++){
        int u=pre[i].u;
        int v=pre[i].v;
        if(fa[u]==fa[v])continue;
        add(fa[u],fa[v]);
        add(fa[v],fa[u]);
    }
    dfs(1,1);
    printf("%d\n",(as+1)/2);
    return 0;
}
Problem F

这道题的关键在于知道

(a|b)+(a&b)=a+b

因此
c[i]+b[i]=na[i]+j=1na[j]i=1nc[i]+b[i]=2nj=1na[j]

接下来我们就能够求出每个 a[i] ,只需要判定是否合法即可
暴力判是 n2 的,但是我们可以按位考虑,这样是 nlogn

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 1e9+7;
const int INF = 0x3f3f3f3f;
LL b[200050];
LL c[200050];
LL a[220045];
LL num[55];
void check(int n,int &flag){
    for(int i=1;i<=n;i++){
        LL bb=0,cc=0;
        for(int j=50;j>=0;j--){
            bb<<=1;cc<<=1;
            if((1LL<<j)&a[i]){
                bb+=num[j];
                cc+=(LL)n;
            }
            else cc+=num[j];
        }
        if(bb!=b[i])flag=0;
        if(cc!=c[i])flag=0;
        if(!flag)return ;
    }
}
int main(void)
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&b[i]);
    }
    for(int i=1;i<=n;i++){
        scanf("%lld",&c[i]);
    }
    LL sum=0;
    for(int i=1;i<=n;i++){
        sum+=(b[i]+c[i]);
    }int flag=1;
    LL csum=sum;
    sum/=((LL)2*n);
    if(sum*(LL)2*n!=csum)flag=0;
    for(int i=1;i<=n;i++){
        a[i]=((b[i]+c[i])-sum)/n;
        if(a[i]*n!=(b[i]+c[i])-sum)flag=0;
        if(a[i]<0)flag=0;
    }
    memset(num,0,sizeof(num));
    if(flag)for(int i=1;i<=n;i++){
        LL p=a[i],k=0;
        while(p){
            if(p&1LL)num[k]++;
            p>>=1;
            k++;
        }
    }
    if(flag)check(n,flag);
    if(flag){
        for(int i=1;i<=n;i++)printf("%lld ",a[i]);
    }
    else puts("-1");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,根据提供的引用内容,我无法理解你具体想要问什么问题。请提供更清晰明确的问题,我将竭诚为你解答。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Codeforces Round 860 (Div. 2)题解](https://blog.csdn.net/qq_60653991/article/details/129802687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [【CodeforcesCodeforces Round 865 (Div. 2) (补赛)](https://blog.csdn.net/t_mod/article/details/130104033)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round 872 (Div. 2)(前三道](https://blog.csdn.net/qq_68286180/article/details/130570952)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值