• Codeforces Round #608 (Div. 2)


    D题:https://codeforces.com/contest/1271/problem/D

    题意:你初始有k只士兵,n个城堡,你要求要逐一攻破。

       给出的信息a[i],b[i],c[i]代表第i个城堡被攻破需要a[i]个士兵(攻破不会造成士兵死亡),在第i个城堡你可以招募b[i]士兵,守护第i个城堡你能得到c[i]的价值。

       守护城堡有俩种方法:1、在攻破 i 城堡后留下一个士兵

                 2、通过往回输送士兵守护;

       然后往回输送题目有给输送的m条路径;  

       问能攻破所有城堡情况下的最大价值

    分析:要求全部攻破,所以我们应该在最后攻破的时候再来进行分配的问题才是正确的;

       因为我们如果要比较早就在 i 城堡设置士兵,也可以在最后的时候分配

       dp[i][j]表示当前在第 i号堡垒,带有第 jj个士兵能获得的最大价值。

       俩个转移:1、///留士兵

            2、///传说士兵回去

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    const int inf=0x3f3f3f3f;
    const int M=5e3+3;
    int a[M],b[M],c[M],dp[M][M],f[M];
    vector<int>val;
    int main(){
        int n,m,k;
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++)
            cin>>a[i]>>b[i]>>c[i];
        for(int i=1;i<=n;i++)
            f[i]=i;
        while(m--){
            int u,v;
            cin>>u>>v;
            f[v]=max(f[v],u);///从最后传送过来
        }
        for(int i=0;i<=n+1;i++){
            for(int j=0;j<M;j++)
                dp[i][j]=-inf;
        }
        dp[1][k]=0;
        for(int i=1;i<=n;i++){
            val.clear();
            for(int j=1;j<=i;j++)
                if(f[j]==i)
                    val.pb(c[j]);
            sort(val.begin(),val.end());
            reverse(val.begin(),val.end());
            for(int j=0;j<M;j++){///留士兵
                if(j>=a[i]&&dp[i][j]>=0)
                    dp[i+1][j+b[i]]=max(dp[i][j],dp[i+1][j+b[i]]);
            }
            for(auto x:val){///传说士兵回去
                for(int j=0;j<M;j++)
                    if(dp[i+1][j]>=0)
                        dp[i+1][j-1]=max(dp[i+1][j-1],dp[i+1][j]+x);
            }
        }
        int ans=-1;
        for(int i=0;i<M;i++)
            ans=max(ans,dp[n+1][i]);
        cout<<ans;
        return 0;
    }
    View Code

    E题:http://codeforces.com/contest/1271/problem/E

    分析:分别考虑偶数和奇数,对于每一个x,反推回去的话,可得[2*x,2*x+1]之间的数都是可到到达的,且x越小能到达的值越多,所以满足单调性,二分解决

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    ll n,k;
    bool check(ll x){
        ll l=x,r=x;
        if(x%2==0)
            r++;
        ll ans=0;
        while(true){
            ans+=min(n,r)-l+1;
            l<<=1;
            r<<=1;
            r++;
            if(l>n)
                break;
        }
        return ans>=k;
    }
    int main(){
        cin>>n>>k;
        ll l=1,r=(n+1)/2;
        ll ans=0;
        while(l<=r){///二分枚举合法奇数
            ll midd=(l+r)>>1;
            if(check(2*midd-1))
                l=midd+1,ans=2*midd-1;
            else
                r=midd-1;
        }
        l=1,r=n/2;
        while(l<=r){///偶数
            ll midd=(l+r)>>1;
            if(check(2*midd))
                l=midd+1,ans=max(2*midd,ans);
            else
                r=midd-1;
        }
        cout<<ans<<endl;
        return 0;
    }
    View Code
  • 相关阅读:
    洛谷P3796 【模板】AC自动机(加强版)(AC自动机)
    洛谷P3203 [HNOI2010]弹飞绵羊(LCT,Splay)
    洛谷P1501 [国家集训队]Tree II(LCT,Splay)
    LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
    [BZOJ3172][TJOI2013]单词 AC自动机
    [BZOJ1968][AHOI2005]COMMON约数研究 数学
    [BZOJ1053][SDOI2005]反素数ant 数学
    [BZOJ1045][HAOI2008]糖果传递 数学
    [BZOJ2733][HNOI2012]永无乡 线段树合并
    [BZOJ1005][HNOI2008]明明的烦恼 数学+prufer序列+高精度
  • 原文地址:https://www.cnblogs.com/starve/p/12060134.html
Copyright © 2020-2023  润新知