zoukankan      html  css  js  c++  java
  • Codeforces Round 608 Div2

    A

    题意

    水题

    思路

    水题

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int main()
    {
        int a,b,c,d,e,f,res=0;
        scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f);
        if(e>f)
        {
            res+=min(a,d)*e;
            d-=min(a,d);
            res+=min(min(b,c),d)*f;
        }
        else
        {
            res+=min(min(b,c),d)*f;
            d-=min(min(b,c),d);
            res+=min(a,d)*e;
        }
        printf("%d
    ",res);
    }
    

    B

    题意

    给一个序列,由W,B组成,代表白色和黑色。每次操作可以选择两个相邻的位置,然后把它们的颜色取反(不是交换),可以操作任意次。找出能否使得序列变全黑或全白的操作。

    思路

    按目标全黑或全白扫一遍即可

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=205;
    
    char input[MAX],s[MAX];
    vector<int>v;
    map<char,char>mp;
    int main()
    {
        mp['W']='B';
        mp['B']='W';
        int n;
        scanf("%d%s",&n,input);
        strcpy(s,input);
        int tot=0;
        for(int i=0; i<n-1; i++)
            if(s[i]=='W')
            {
                s[i]='B';
                s[i+1]=mp[s[i+1]];
                tot++;
                v.push_back(i+1);
            }
        if(s[n-1]=='B')
        {
            printf("%d
    ",tot);
            for(int i=0; i<v.size(); i++)
                printf("%d ",v[i]);
            printf("
    ");
            return 0;
        }
        tot=0;
        v.clear();
        strcpy(s,input);
        for(int i=0; i<n-1; i++)
            if(s[i]=='B')
            {
                s[i]='W';
                s[i+1]=mp[s[i+1]];
                tot++;
                v.push_back(i+1);
            }
        if(s[n-1]=='W')
        {
            printf("%d
    ",tot);
            for(int i=0;i<v.size();i++)
                printf("%d ",v[i]);
            printf("
    ");
            return 0;
        }
        printf("-1
    ");
    }
    
    

    C

    题意

    有一个学校,坐标x,y。有若干学生,家在不同的地方,上学走和学校构成矩形内的任意曼哈顿路径,求某一点坐标,使得上学路上可以经过该点的学生最多。

    思路

    显然可以分为四个象限和四个坐标轴。分别计算一下上面的学生人数。然后取最大值。结果就是最大的那个区域的坐标轴离学校远一格。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int quadrant[5],axes[5];
    
    int main()
    {
        int n,sx,sy,x,y;
        scanf("%d%d%d",&n,&sx,&sy);
        while(n--)
        {
            scanf("%d%d",&x,&y);
            if(x==sx)
            {
                if(y>sy)
                    axes[2]++;
                else
                    axes[4]++;
            }
            if(y==sy)
            {
                if(x>sx)
                    axes[1]++;
                else
                    axes[3]++;
            }
            if(x>sx&&y>sy)
                quadrant[1]++;
            if(x<sx&&y>sy)
                quadrant[2]++;
            if(x<sx&&y<sy)
                quadrant[3]++;
            if(x>sx&&y<sy)
                quadrant[4]++;
        }
        int maxx=-1;
        for(int i=1; i<=4; i++)
        {
            int cur=axes[i]+quadrant[i]+quadrant[i==1?4:i-1];
            if(maxx<cur)
            {
                maxx=cur;
                if(i==1)x=sx+1,y=sy;
                if(i==2)x=sx,y=sy+1;
                if(i==3)x=sx-1,y=sy;
                if(i==4)x=sx,y=sy-1;
            }
        }
        printf("%d
    %d %d
    ",maxx,x,y);
    }
    

    D

    题意

    n个城堡,你带兵从1-n按顺序攻打。初始有k个士兵,攻打i号城堡需要ai个士兵(只是需要,不会有伤亡)。打完以后可以征兵,i号城堡可以征兵bi个,城堡攻打下来以后可以驻守,驻守需要1个士兵。驻守i号城堡可以得分ci分。此外还有一些秘密通道,u-v,代表可以从u号城堡派一个士兵去驻守v号城堡(保证u>v)。求能否攻打下全部的城堡,若能,则输出最大得分,否则输出 -1

    思路

    首先由于必须全部攻打下来才有得分,所以很容易想到一些贪心的结论:

    1. 征兵一定优于不征兵
    2. 如果当前城堡可以后面再驻守,那后面再驻守一定优于当前就驻守,并且越后驻守越好、

    这样决策就只剩下:

    1. 当前城堡不能后面再驻守,决策要不要在这里驻守
    2. 当前城堡有秘密通道,决策要不要派兵回去驻守。

    很明显是动态规划的问题。然后从数据范围很容易想到dp[i][j]表示到第i个城堡时有j个士兵时能获得的最大收益。转移则 dp[i][j]dp[i-1][j-bi] 转移得到。然后再由 dp[i][j]dp[i][j-1] 转移,取决于当前城堡有没有秘密通道。

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    const int MAX=5005;
    
    int a[MAX],b[MAX],c[MAX],dp[MAX][MAX],pre[MAX];
    vector<int>out[MAX],in[MAX],cur;
    
    int main()
    {
        int n,m,k,u,v;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=n;i++)
            scanf("%d%d%d",&a[i],&b[i],&c[i]),pre[i]=pre[i-1]+b[i];
        while(m--)
        {
            scanf("%d%d",&u,&v);
            in[v].push_back(u);
        }
        for(int i=1;i<=n;i++)
        {
            if(!in[i].size())continue;
            sort(in[i].begin(),in[i].end());
            out[in[i].back()].push_back(i);
        }
        memset(dp,-1,sizeof dp);
        dp[0][k]=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=a[i]+b[i];j<=pre[i]+k;j++)
            {
                dp[i][j]=dp[i-1][j-b[i]];
                if(dp[i][j]==-1)continue;
                if(!in[i].size()&&j>=1)
                    dp[i][j-1]=max(dp[i][j-1],dp[i][j]+c[i]);
                if(out[i].size())
                {
                    cur.clear();
                    int sum=0;
                    for(int l=0;l<out[i].size();l++)
                        cur.push_back(c[out[i][l]]);
                    sort(cur.begin(),cur.end(),greater<int>());
                    for(int l=0;l<cur.size();l++)
                    {
                        sum+=cur[l];
                        if(j-l-1>=0)
                            dp[i][j-l-1]=max(dp[i][j-l-1],dp[i][j]+sum);
                        if(j-l-2>=0&&!in[i].size())
                            dp[i][j-l-2]=max(dp[i][j-l-2],dp[i][j]+sum+c[i]);
                    }
                }
            }
        }
        int res=-1;
        for(int i=0;i<=pre[n]+k;i++)
            res=max(res,dp[n][i]);
        printf("%d
    ",res);
    }
    

    E

    题意

    定义一个函数f

    [egin{eqnarray} f(x)=egin{cases} frac x2 &x为偶数\ x-1 &x为奇数 end{cases} end{eqnarray} ]

    对于一个数x连续调用f(x) ,得到一个序列。如对 15 得到 15,14,7,6,3,2,1 。现在给出 n,k ,求一个数 x ,使得 x1-n 中各数的序列中,至少有 k 个序列包含 x

    思路

    很容易想到答案具有单调性。但是通过样例可以发现不是单纯的单调性,要分奇偶。奇数答案和偶数答案内部都具有单调性。所以分奇偶二分答案,复杂度也是可行的。所以问题转化为判断一个数x,在给定的序列中到底出现几次。把序列画成一棵树可以找到规律。

    如图可得规律,x的出现次数就是以x为根节点的子树的节点个数(最大值要限制在n之内)。由规律可以 log(n) 的找出 x 的出现次数。总复杂度log^2(n)

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    
    ll n,k;
    
    ll check(ll x)
    {
        ll a,b,ans=0;
        if(x&1ll)
            a=b=x;
        else
            a=x,b=x+1;
        while(a<=n)
        {
            ans+=min(n,b)-a+1;
            a=a*2;
            b=b*2+1;
        }
        return ans;
    }
    
    int main()
    {
        scanf("%I64d%I64d",&n,&k);
        ll L=1,R=n/2+(n&1),res=-1;
        while(L<=R)
        {
            ll mid=(L+R)>>1;
            if(check(mid*2-1)>=k)
            {
                L=mid+1;
                res=max(res,mid*2-1);
            }
            else
                R=mid-1;
        }
        L=1,R=n/2;
        while(L<=R)
        {
            ll mid=(L+R)>>1;
            if(check(mid<<1)>=k)
            {
                L=mid+1;
                res=max(res,mid<<1);
            }
            else
                R=mid-1;
        }
        printf("%I64d
    ",res);
    }
    
  • 相关阅读:
    韩式英语
    Daily dictation 听课笔记
    words with same pronunciation
    you will need to restart eclipse for the changes to take effect. would you like to restart now?
    glottal stop(britain fountain mountain)
    education 的发音
    第一次用Matlab 的lamada语句
    SVN的switch命令
    String的split
    SVN模型仓库中的资源从一个地方移动到另一个地方的办法(很久才解决)
  • 原文地址:https://www.cnblogs.com/cryingrain/p/12405403.html
Copyright © 2011-2022 走看看