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;
}
发布了73 篇原创文章 · 获赞 13 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/IDrandom/article/details/53190198
今日推荐