• Codeforces Round #661 (Div. 3) A~E1


    Codeforces Round #661 (Div. 3) A~E1

    原作者为 DOEMsy@cnblogs, 本作品采用 CC 4.0 BY 进行许可,转载请注明出处。

    上分场找回了点自信。

    https://codeforces.com/contest/1399

    A. Remove Smallest

    题意

    给定一个数组 (a_1,a_2,...,a_n) ,每次操作可以选取数组中两个相差不大于 (1) 的数字,删除其中一个。

    询问能否删到最后剩余一个数字。

    解题

    保证数组有序后,相邻元素差值不超过 (1) 即可。

    #include<bits/stdc++.h>
    //#include<windows.h>
    #define ll long long
    #define fr(i,n) for(ll i=0;i<n;i++)
    
    using namespace std;
    
    int main(){
    
        int t;cin>>t;
        while(t--){
            int n;cin>>n;
            int a[55];
            fr(i,n) cin>>a[i];
            sort(a,a+n);
            int p = 1;
            fr(i,n-1){
                if(a[i+1]-a[i]>1)   p++;
            }
            //cout<<1<<endl;
            if(p>1)    cout<<"NO"<<endl;
            else        cout<<"YES"<<endl;
        }
    
        return 0;
    }
     
    

    B. Gifts Fixing

    题意

    (n) 个礼物,每个礼物由 (a_i) 个糖果和 (b_i) 个橘子组成。

    每次可以对一个礼物进行以下操作:

    • 吃掉一个糖果;
    • 吃掉一个橘子;
    • 吃掉一个糖果和一个橘子。

    询问最少多少次操作可以使得所有礼物的糖果和橘子都相同。

    解题

    简单贪心,将所有的糖果和橘子变成分别变成最少的数量,每一堆的最少花费为 (max(a_i-a_{min},b_i-b_{min})) ,求和即可。

    #include<bits/stdc++.h>
    //#include<windows.h>
    #define ll long long
    #define fr(i,n) for(ll i=0;i<n;i++)
    
    using namespace std;
    
    int main(){
    
        int t;cin>>t;
        while(t--){
            ll a[55],b[55];
            int n;cin>>n;
            fr(i,n) cin>>a[i];
            fr(i,n) cin>>b[i];
            ll mina = *min_element(a,a+n);
            ll minb = *min_element(b,b+n);
            ll ans = 0;
            fr(i,n){
                ans+=max(a[i]-mina,b[i]-minb);
            }
            cout<<ans<<endl;
        }
    
        return 0;
    }
     
    

    C. Boats Competition

    题面

    有一群人,战斗力为 (w_1,w_2,...,w_n) ,要求两两组队,且每个队伍的战斗力必须相同。

    询问最多可以组成多少个队伍。

    解题

    由于人数和战斗力范围较小,可以直接在 ([2,2n]) 内遍历队伍战斗力范围,取组成数量最多值,复杂度 (O(2n^2))

    #include<bits/stdc++.h>
    //#include<windows.h>
    #define ll long long
    #define fr(i,n) for(ll i=0;i<n;i++)
    #define memset0(dp) memset(dp,0,sizeof(dp))
    
    using namespace std;
    
    int main(){
        
        int t;cin>>t;
        while(t--){
            int n;cin>>n;
            int a[550];memset0(a);
            fr(i,n){
                int inp;cin>>inp;
                a[inp]++;
            }
            int  maxs = 0,maxnum = 0;
            frr(s,2,2*n+1){
                int num = 0;
                frr(i,1,n+1){
                    if(s-i>0)   num+=min(a[i],a[s-i]);
                }
                num/=2;
                maxnum = max(num,maxnum);
            }
            cout<<maxnum<<endl;
        }
        return 0;
    }
     
    

    D. Binary String To Subsequences

    题意

    给定一个由 (01) 组成的字符串 (S),问最少分成多少个子串,使得每个子串 (01) 交错。

    并且输出每一个字符被分配到的子串编号。

    解题

    注意题中说的是子串,不是连续子串。

    类似 (dp) 的思路,将前面的所有子串状态存储,对于当前字符 (S_i) 有:

    • 如果存在结尾与 (S_i) 不同的子串,则可以用 (S_i) 续接该子串。
    • 否者用 (S_i) 新建一个子串。

    关于子串的存储只需要记录结尾和编号即可,复杂度 (O(n))

    #include<bits/stdc++.h>
    //#include<windows.h>
    #define ll long long
    
    #define fr(i,n) for(ll i=0;i<n;i++)
    #define frs(i,n,flag)   for(ll i=0;i<n&&flag;i++)
    #define e5 100005
    #define print_arr(begin,end)    for(auto it = begin;it!=end;it++)  cout<<*it<<" "; cout<<endl;
    
    using namespace std;
    int a[2*e5];
    int main(){
        int t;cin>>t;
        while(t--){
            int n;cin>>n;
            string inp;cin>>inp;
            int maxsz = 0;
            //fr(i,n) a[i] = 0;
            stack<int>ct[2];
            fr(i,n){
                if(!ct[!(inp[i]-'0')].empty()){
                    a[i] = ct[!(inp[i]-'0')].top();
                    ct[!(inp[i]-'0')].pop();
                    ct[(inp[i]-'0')].push(a[i]);
                }else{
                    ct[(inp[i]-'0')].push(++maxsz);
                    a[i] = maxsz;
                }
            }
            cout<<maxsz<<endl;
            print_arr(a,a+n);
    
        }
    
        return 0;
    }
    

    E1. Weights Division (easy version)

    题意

    给定一棵带边权的树,每次操作可以选择一条边,使其权值 (w_i = lfloorfrac{w_i}{2} floor)

    询问至少多少次操作,可以使得叶节点到根部的路径权总和小于等于 (S)

    解题

    贪心,选取一个边会对权值和产生的影响为 ((w_i-lfloorfrac{w_i}{2} floor)*cnt)(cnt) 为经过该边的叶节点数量,优先选取影响大的。

    (dfs) 跑出每一条边的 (w_i,cnt),再以单调队列维护,不断操作,直到和小于等于 (S)

    复杂度 (O(nlogn))

    #include<bits/stdc++.h> 
    //#include<windows.h>
    #define ll long long
    
    #define fr(i,n) for(ll i=0;i<n;i++)
    #define frs(i,n,flag)   for(ll i=0;i<n&&flag;i++)
    
    #define frr(i,j,n) for(ll i=j;i<n;i++)
    #define r_frr(i,j,n) for(ll i=n-1;i>=j;i--)
    
    #define frrs(i,j,n,flag)    for(ll i=j;i<n&&flag;i++)
    #define r_frrs(i,j,n,flag)    for(ll i=n-1;i>=j&&flag;i--)
    
    
    #define yes "yes"
    #define no  "no"
    
    #define memset0(dp) memset(dp,0,sizeof(dp))
    #define min_get(a,b) a = min(a,b)
    #define max_get(a,b) a = max(a,b)
    #define PI  3.14159265354
    
    #define print_arr(begin,end)    for(auto it = begin;it!=end;it++)  cout<<*it<<" "; cout<<endl;
    #define log_this(name,value)    cout<<name<<": "<<value<<endl;
    
    #define e5 100005
    #define e6 1000006
    
    using namespace std;
    ll     to_ll(string s)    {stringstream ss;ss<<s<<endl;ll a;ss>>a;return a;}
    string  to_str(double a)    {stringstream ss;ss<<a<<endl;return ss.str();}
    template<class T>inline void read(T &x){T f=1;x=0;char c=getchar();while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}x*=f;}
    
    map<int,ll>eg[1*e5];
    
    struct cst_cnt{
        ll cst,cnt;
        cst_cnt(ll cs,ll cn){cst = cs,cnt = cn;}
    
        bool operator < (const cst_cnt o)const{
            return (cst-cst/2)*cnt<(o.cst-o.cst/2)*o.cnt;
        }
    };
    
    priority_queue<cst_cnt>cost;
    
    ll sum;
    
    ll dfs(int i,int last){
        ll cst;
        if(i==last) cst = 0;
        else cst = eg[i][last];
        ll cnt = 0;
        if(eg[i].size()==1&&i!=last) cnt = 1;
        else{
            for(auto it:eg[i]){
                if(it.first!=last){
                    cnt += dfs(it.first,i);
                }
            }
        }
        sum += cnt*cst;
        cost.push(cst_cnt(cst,cnt));
        return cnt;
    }
    
    int main(){
    
        int t;cin>>t;
        while(t--){
            ll n,s;cin>>n>>s;
            frr(i,1,n+1) eg[i].clear();
            ll v,u,w;
            #define p(a,b) pair<int,ll>(a,b)
            fr(i,n-1){
                cin>>v>>u>>w;
                eg[v].insert(p(u,w));
                eg[u].insert(p(v,w));
            }
            while(!cost.empty()) cost.pop();
            sum = 0;
            dfs(1,1);
    
            ll ans = 0;
            while(sum>s){
                cst_cnt tmp = cost.top();
                sum -= (tmp.cst-tmp.cst/2)*tmp.cnt;
                tmp.cst/=2;
                cost.pop();
                cost.push(tmp);
                ans++;
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    @PathVariable和@RequestParam的区别,@SessionAttributes
    forward和redirect的区别
    JSP页面的静态包含和动态包含
    ConcurrentHashMap源码解析
    Jdk1.6 JUC源码解析(1)-atomic-AtomicXXX
    最小生成树
    tomcat启动项目内存溢出问题
    强引用,弱引用,4种Java引用浅解(涉及jvm垃圾回收)
    CXF 在WAS上报Unmarshalling Error的问题
    CXF处理Date类型的俩种方式
  • 原文地址:https://www.cnblogs.com/DOEMsy/p/13448928.html
Copyright © 2020-2023  润新知