• Codeforces Round #670 (Div. 2) ABC 题解


    A. Subset Mex

    题意:把一个集合(可能有重复元素)分成两部分,使得每部分的缺少的最小非负整数的和最大。

    其中在原序列里面就缺少的那个最小非负整数肯定是躲不掉的。就先把这个数之前的所有数放在一个集合,另外的放另一个集合。这样贪心是最优的。

    view code
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<map>
    #include <queue>
    #include<sstream>
    #include <stack>
    #include <set>
    #include <bitset>
    #include<vector>
    #define FAST ios::sync_with_stdio(false)
    #define abs(a) ((a)>=0?(a):-(a))
    #define sz(x) ((int)(x).size())
    #define all(x) (x).begin(),(x).end()
    #define mem(a,b) memset(a,b,sizeof(a))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define rep(i,a,n) for(int i=a;i<=n;++i)
    #define per(i,n,a) for(int i=n;i>=a;--i)
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> PII;
    const int maxn = 1e5+200;
    const int inf=0x3f3f3f3f;
    const double eps = 1e-7;
    const double pi=acos(-1.0);
    const int mod = 1e9+7;
    inline int lowbit(int x){return x&(-x);}
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
    inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
    inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
    inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
    inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
    int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
    
    ll a[maxn];
    ll Map[150];
    
    int main()
    {
        int kase;
        cin>>kase;
        while(kase--)
        {
            ll n = read();
            mem(Map,0);
            rep(i,1,n) a[i] = read(), Map[a[i]]++;
            ll obj = 0;
            rep(i,0,n) if(!Map[i]) {obj = i; break;}
            rep(i,0,obj) Map[i]--;
            rep(i,1,n) if(Map[a[i]]==0) a[i] = -1;
            mem(Map,0);
            rep(i,1,n) Map[a[i]]++;
            ll obj1 = 0;
            rep(i,0,n) if(!Map[i]) {obj1 = i; break; }
            cout<<obj+obj1<<'
    ';
        }
        return 0;
    }
    
    

    B. Maximum Product

    题意:给一个序列,找出一个五元组,使得其积最大。

    思路:贪心。分类讨论一下
    全负
    四负一正
    三负二正
    二负三正
    一负四正
    全正
    的情况。如果结果是负数的就挑各自绝对值最小的,反之就挑绝对值最大的几个。

    view code
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<map>
    #include <queue>
    #include<sstream>
    #include <stack>
    #include <set>
    #include <bitset>
    #include<vector>
    #define FAST ios::sync_with_stdio(false)
    #define abs(a) ((a)>=0?(a):-(a))
    #define sz(x) ((int)(x).size())
    #define all(x) (x).begin(),(x).end()
    #define mem(a,b) memset(a,b,sizeof(a))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define rep(i,a,n) for(int i=a;i<=n;++i)
    #define per(i,n,a) for(int i=n;i>=a;--i)
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> PII;
    const int maxn = 2e5+200;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const double eps = 1e-7;
    const double pi=acos(-1.0);
    const int mod = 1e9+7;
    inline int lowbit(int x){return x&(-x);}
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
    inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
    inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
    inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
    inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
    int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
    
    ll a[maxn];
    ll dp[maxn];
    vector<ll> neg;
    vector<ll> pos;
    
    int main()
    {
        int kase;
        cin>>kase;
        while(kase--)
        {
            neg.clear(), pos.clear();
            ll n = read();
            rep(i,1,n) a[i] = read();
            rep(i,1,n)
            {
                if(a[i]<0) neg.pb(a[i]);
                else  pos.pb(a[i]);
            }
            ll ans = -inf;
            if(neg.size()+pos.size()>=5)
            {
                sort(neg.begin(), neg.end());
                sort(pos.begin(),pos.end());
    
                if(neg.size()>=4&&pos.size()>=1)
                ans = max((ll)neg[0]*neg[1]*neg[2]*neg[3]*pos[pos.size()-1], ans);
    
                if(neg.size()>=3&&pos.size()>=2)
                ans = max((ll)neg[neg.size()-1]*neg[neg.size()-2]*neg[neg.size()-3]*pos[0]*pos[1],ans);
    
                if(neg.size()>=2&&pos.size()>=3)
                ans = max((ll)neg[0]*neg[1]*pos[pos.size()-1]*pos[pos.size()-2]*pos[pos.size()-3],ans);
    
                if(neg.size()>=1&&pos.size()>=4)
                ans = max((ll)neg[neg.size()-1]*pos[0]*pos[1]*pos[2]*pos[3],ans);
    
                if(pos.size()>=5)
                ans = max((ll)pos[pos.size()-1]*pos[pos.size()-2]*pos[pos.size()-3]*pos[pos.size()-4]*pos[pos.size()-5],ans);
    
                if(neg.size()>=5)
                ans = max((ll)neg[neg.size()-1]*neg[neg.size()-2]*neg[neg.size()-3]*neg[neg.size()-4]*neg[neg.size()-5], ans);
            }
            cout<<ans<<'
    ';
        }
        return 0;
    }
    
    

    题意:给一颗树,定义一个特殊点为删除它和连接的边后剩下子树最大节点数最小。现在让你在保持树结构的前提下,改一条边,使得这个特殊点唯一。

    思路:其实这个特殊点就是重心。
    重心怎么求呢?
    随便找个结点当根,先统计所有结点的子树包含结点,然后用一个变量存每个结点子树数量的最大值。其中最大值最小的那个即是重心。
    重心有个性质就是如果不唯一,只能最多存在两个,且相邻。
    那么这个题求完重心后就看看唯一与否,是的话直接随便找条和它相连的边删掉再连回去。不是的话就把另一个重心的另外一个相连点连到当前这个上。

    view code
    #include<iostream>
    #include<string>
    #include<algorithm>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<map>
    #include <queue>
    #include<sstream>
    #include <stack>
    #include <set>
    #include <bitset>
    #include<vector>
    #define FAST ios::sync_with_stdio(false)
    #define abs(a) ((a)>=0?(a):-(a))
    #define sz(x) ((int)(x).size())
    #define all(x) (x).begin(),(x).end()
    #define mem(a,b) memset(a,b,sizeof(a))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define rep(i,a,n) for(int i=a;i<=n;++i)
    #define per(i,n,a) for(int i=n;i>=a;--i)
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> PII;
    const int maxn = 1e5+200;
    const int inf=0x3f3f3f3f;
    const double eps = 1e-7;
    const double pi=acos(-1.0);
    const int mod = 1e9+7;
    inline int lowbit(int x){return x&(-x);}
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y){if(!b){d=a,x=1,y=0;}else{ex_gcd(b,a%b,d,y,x);y-=x*(a/b);}}//x=(x%(b/d)+(b/d))%(b/d);
    inline ll qpow(ll a,ll b,ll MOD=mod){ll res=1;a%=MOD;while(b>0){if(b&1)res=res*a%MOD;a=a*a%MOD;b>>=1;}return res;}
    inline ll inv(ll x,ll p){return qpow(x,p-2,p);}
    inline ll Jos(ll n,ll k,ll s=1){ll res=0;rep(i,1,n+1) res=(res+k)%i;return (res+s)%n;}
    inline ll read(){ ll f = 1; ll x = 0;char ch = getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1; ch = getchar();}while(ch>='0'&&ch<='9') x = (x<<3) + (x<<1) + ch - '0',  ch = getchar();return x*f; }
    int dir[4][2] = { {1,0}, {-1,0},{0,1},{0,-1} };
    
    ll Map[maxn];
    vector<vector<ll> > D(maxn);
    ll siz[maxn];
    ll son[maxn];
    bool vis[maxn];
    ll n;
    
    ll dfs(ll x)
    {
        ll cur = 0;
        ll ma = 0;
        vis[x] = 1;
        for(int i=0 ;i<D[x].size(); i++)
        {
            ll y = D[x][i];
            if(vis[y]) continue;
            cur += dfs(y);
            ma = max(ma,siz[y]);
        }
        son[x] = ma = max(ma, n-cur-1);
        siz[x] = cur+1;
        return cur+1;
    }
    
    int main()
    {
        int kase;
        cin>>kase;
        while(kase--)
        {
            n = read();
            rep(i,0,n+1) Map[i] = 0, D[i].clear(), vis[i] = 0, son[i] = 0, siz[i] = 0;
            rep(i,1,n-1)
            {
                ll x = read(), y = read();
                D[x].pb(y);
                D[y].pb(x);
            }
            ll m = dfs(1);
    
            ll obj = 1;
            ll mi = inf;
            rep(i,1,n)
            {
                Map[son[i]]++;
                if(son[i]<mi) mi = son[i], obj = i;
            }
            if(Map[mi]==1)
            {
                ll v = D[obj][0];
                cout<<obj<<' '<<v<<'
    ';
                cout<<obj<<' '<<v<<'
    ';
            }
            else
            {
                ll v = 1;
                for(int i=0; i<D[obj].size(); i++)
                if(son[D[obj][i]]==mi)  {v=D[obj][i]; break;}
                ll vv = 1;
                for(int i=0; i<D[v].size(); i++) if(D[v][i]!=obj) {vv=D[v][i]; break;}
                cout<<vv<<' '<<v<<'
    ';
                cout<<vv<<' '<<obj<<'
    ';
            }
        }
        return 0;
    }
    
    

  • 相关阅读:
    Python的学习之旅———UDP
    Python的学习之旅———socket ,socketserver
    Python的学习之旅———time 模块
    python的学习之旅---面向对象
    Python的学习之旅———re 模块正则表达式
    有事没事找高宇哥聊天,李泽军爸妈聊天,管那么多人干嘛,活好自己
    还有教师观没有记
    Navicat中怎么查看数据库密码
    Oracle 删除用户时出现异常ora-01922: CASCADE must bu specified to drop 用户名
    kali使用sqlmap注入dvma
  • 原文地址:https://www.cnblogs.com/Bgwithcode/p/13660790.html
Copyright © 2020-2023  润新知