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);
    }
    
  • 相关阅读:
    Android5.0全透明状态栏效果
    从关系库导入数据到hive-hbase表中
    Find Minimum in Rotated Sorted Array II 旋转数组中找最小值(有反复元素) @LeetCode
    深度解析国内首个云原生数据库POLARDB的“王者荣耀”
    深度解析国内首个云原生数据库POLARDB的“王者荣耀”
    nodejs中httpserver的安装和使用
    Java的循环语句
    Java的循环语句
    Java的循环语句
    Mybatis-generator生成Service和Controller
  • 原文地址:https://www.cnblogs.com/cryingrain/p/12405403.html
Copyright © 2011-2022 走看看