• 2020牛客暑期多校训练营(第三场)


    Contest Info


    传送门

    Solved A B C D E F G H I J K L
    8 / 13 O O Ø Ø O - Ø - - - - O
    • O 在比赛中通过
    • Ø 赛后通过
    • ! 尝试了但是失败了
    • - 没有尝试

    Solutions


    A. Clam and Fish

    贪心模拟。

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/18 12:23:24
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
    void run() {
        int n;
        cin >> n;
        string s;
        cin >> s;
        int ans = 0;
        int p = 0;
        int d = 0;
        for (int i = 0; i < n; i++) {
            if (s[i] == '0') {
                if (p > d) {
                    --p;
                    ++ans;
                } else if (d > 0) {
                    --d;
                    ++ans;
                }
            } else if (s[i] == '1') {
                if (p > d) {
                    //make it clam and use it later
                    ++d;
                } else {
                    ++p;
                }
            } else {
                ++ans;
            }
        }
        ans += d;
        cout << ans << '
    ';
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    B. Classical String Problem

    将序列的翻转看作指针的偏移。

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/18 12:11:54
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
    void run() {
        string s; cin >> s;
        int n = s.length();
        int q; cin >> q;
        int p = 0;
        while (q--) {
            string op;
            int x;
            cin >> op >> x;
            if (op == "M") {
                if (x > 0) {
                    p = (p + x) % n;
                } else {
                    p = (p + x + n) % n;
                }
            } else {
                int pos = (p + x - 1) % n;
                cout << s[pos] << '
    ';
            }
        }
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    

    C. Operation Love

    通过叉积求出有向面积判断图形给出的方向,之后直接check即可。

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/18 21:11:26
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
    void run() {
        int n = 20;
        vector<double> x(n + 1), y(n + 1);
        for (int i = 0; i < n; i++) {
            cin >> x[i] >> y[i];
        }
        x[n] = x[0], y[n] = y[0];
        auto sq = [&] (double t) {
            return t * t;
        };
        vector<double> d(n);
        double tot = 0;
        for (int i = 0; i < n; i++) {
            d[i] = sqrt(sq(x[i + 1] - x[i]) + sq(y[i + 1] - y[i]) + 0.5);
            tot += x[i] * y[i + 1] - x[i + 1] * y[i];
        }
        if (tot < 0) {
            reverse(all(d));
        }
        int a, b;
        for (int i = 0; i < n; i++) {
            if ((int)(d[i] + 0.5) == 6) a = i;
            if ((int)(d[i] + 0.5) == 8) b = i;
        }
        if ((a + 2) % n == b) {
            cout << "right" << '
    ';
        } else {
            cout << "left" << '
    ';
        }
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    D. Points Construction Problem

    题意:
    无限大平面内要放置(n)个黑点,使得有(m)对黑点、白点相邻。
    (n,mleq 200)

    思路:
    显然是一个构造题,我们需要构造出刚好符合条件的方案。
    首先考虑不合法的情况:(m)为奇数或者(m>4n)显然不合法,还有一个问题就是答案的下界。将问题转化为周长问题,那么面积相同的情况下,圆形的周长最小,所以下界应该是多个黑点紧凑在一起的情况。假设有(a)(b)列,那么周长即为(2(a+b)),并且满足(acdot bgeq n)。据此可以算出下界。
    那么之后直接构造,如果有(a,b)符合条件那么直接输出;
    否则观察我们拿走一个到无穷远的地方,周长只会增加(2)或者(4),所以我们直接这样操作就行。
    最后如果周长还差(2),那么我们将两个黑点拼在一起即可。

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/19 09:35:17
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    void err(int x) {cerr << x;}
    void err(long long x) {cerr << x;}
    void err(double x) {cerr << x;}
    void err(char x) {cerr << '"' << x << '"';}
    void err(const string &x) {cerr << '"' << x << '"';}
    void _print() {cerr << "]
    ";}
    template<typename T, typename V>
      void err(const pair<T, V> &x) {cerr << '{'; err(x.first); cerr << ','; err(x.second); cerr << '}';}
    template<typename T>
      void err(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? "," : ""), err(i); cerr << "}";}
    template <typename T, typename... V>
      void _print(T t, V... v) {err(t); if (sizeof...(v)) cerr << ", "; _print(v...);}
    #ifdef Local
    #define dbg(x...) cerr << "[" << #x << "] = ["; _print(x)
    #else
    #define dbg(x...)
    #endif
    //head
    const int N = 1e5 + 5;
    void run() {
        int n, m;
        cin >> n >> m;
        
        int a, b;
        int Min = INF;
        for (int i = 1; i <= m; i++) {
            for (int j = 1; j <= m; j++) {
                if (i * j >= n && (i - 1) * j < n && i * (j - 1) < n) {
                    if (2 * (i + j) < Min) {
                        Min = 2 * (i + j);
                        a = i, b = j;
                    }
                    if (2 * (i + j) == m) {
                        a = i, b = j;
                        goto nxt;
                    }
                }
            }
        } nxt:;
        if (m & 1 || m > 4 * n || m < 2 * (a + b)) {
            cout << "No" << '
    ';
            return;
        }
        dbg(a, b);
        vector<pii> ans;
        int tot = 2 * (a + b);
        int r = n;
        for (int i = 1; i <= a && r; i++) {
            for (int j = 1; j <= b && r; j++, --r) {
                ans.push_back(MP(i, j));
            }
        }
        vector<pii> res;
        int x = 1000000, y = 100000000;
        while (sz(ans) > 1 && m - tot >= 4) {
            pii now = ans.back();
            ans.pop_back();
            if (now.se == 1 || now.fi == 1) {
                tot += 2;
            } else {
                tot += 4;
            }
            res.push_back(MP(x, y));
            x += 2;
        }
        assert(m - tot <= 2);
        if (m - tot >= 2) {
            pii now = ans.back();
            ans.pop_back();
            if (now.fi == 1 || now.se == 1) {
                res.push_back(MP(x, y));
            } else {
                res.push_back(MP(now.fi - 1, b + 1));
            }
        }
        cout << "Yes" << '
    ';
        for (auto it : res) {
            cout << it.fi << ' ' << it.se << '
    ';
        }
        for (auto it : ans) {
            cout << it.fi << ' ' << it.se << '
    ';
        }
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    E. Two Matchings

    考虑将数组升序排序,那么如果只找一个序列的话显然((1,2),(3,4),cdots)这样进行匹配,我们将其看作((-,+,-,+,-,+,...,-,+))
    对于第二个序列,比较直观的方法是((-,-,+,-,+,...,+,+))。会发现此时答案为(2(a_n-a_1))
    但这并不是最优解,观察我们可以交换第二个序列中某个(+)和前面一个(-)的顺序,这样能使得答案最小。
    并且有一个这样的性质,对于(i,i+1,i+2,i+3)这四个位置,如果我们交换了(i+2,i+3),那么不能交换(i,i+1)。并且也不能交换(2,3)以及(n-2,n-1)
    所以根据这一点直接(dp)就行。
    详见代码:

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/18 13:37:37
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
    void run() {
        int n;
        cin >> n;
        vector<ll> a(n);
        ll ans = 0;
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        sort(all(a));
        for (int i = 1; i < n; i += 2) {
            ans += a[i] - a[i - 1];
        }
        vector<ll> dp(n);
        dp[0] = -a[0];
        dp[2] = -a[0] - a[1] + a[2];
        for (int i = 4; i < n - 1; i += 2) {
            dp[i] = dp[i - 2] + a[i] - a[i - 1];
            if (i < n - 2) {
                dp[i] = min(dp[i], dp[i - 4] - a[i - 3] + a[i - 2] + a[i - 1] - a[i]);
            }
        }
        ans += dp[n - 2] + a[n - 1]; 
        cout << ans << '
    ';
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    F. Fraction Construction Problem

    题意:
    构造题。
    给出(a,bleq 2cdot 10^6)
    然后找到(c,d,e,f),满足:

    • (frac{c}{d}-frac{e}{f}=frac{a}{b});
    • (d<b,f<b);
    • (1leq c,eleq 4cdot 10^{12}).

    无解则输出-1。

    思路:
    (g=gcd(a,b)),首先注意到如果(g>1)那么就win了,方案很容易构造。
    接下来就只用考虑(g=1)的情况,大体思路就是构造(d,f)使得(dcdot f=b),之后再解一个(cf-ed=a)的二元一次方程。
    方程有解则需要保证(gcd(d,f)|a),又因为(dcdot f = b,gcd(a,b)=1)。也就是我们找的(d,f)一定是互质的,否则就不可能存在解。
    所以找到这样的两个数过后用exgcd解一下方程就行。
    但这里我有个问题,就是在exgcd的过程中先乘(c)会wa,后乘(c)就A了,但实际上两种写法都没问题,不知道是哪里的原因...

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/18 15:52:18
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2e6 + 5;
    const ll MAX = 4e18;
        
    int v[N], prime[N];
    int num;
    void Euler() {
        v[1] = 1;
        for(int i = 2; i < N; i++) {
            if(v[i] == 0) {
                v[i] = i;
                prime[++num] = i;
            }
            for(int j = 1; j <= num && prime[j] * i < N; j++) {
                v[prime[j] * i] = prime[j] ;
            }
        }
    }
        
    void exgcd(ll a, ll b, ll &x, ll &y) {
        if(b == 0) {
            x = 1, y = 0;
            return ;
        }
        exgcd(b,a%b,x,y);
        ll z = x ;
        x = y;
        y = z - y * (a / b);
    }
    //ax + by = c
    ll calc(ll a, ll b, ll c) {
        ll x, y;
        ll g = __gcd(a, b);
        assert(g == 1);
        // g = 1
        a /= g, b /= g, c /= g;
        exgcd(a, b, x, y);
        assert(x <= MAX / c);
        // x *= c;
        x = (x % b + b) % b;
        if (x == 0) x += b;
        x *= c;
        return x;
    }
        
    void run() {
        int a, b;
        cin >> a >> b;
        int g = __gcd(a, b);
        if (g == 1) {
            // c / d - e / f = a / b
            // cf - ed = a
            if (v[b] == b) {
                cout << -1 << ' ' << -1 << ' ' << -1 << ' ' << -1 << '
    ';
            } else {
                int f = 1;
                int x = b;
                while (x % v[b] == 0) {
                    x /= v[b];
                    f *= v[b];
                }
       
                if (x == 1) {
                    cout << -1 << ' ' << -1 << ' ' << -1 << ' ' << -1 << '
    ';
                    return;
                }
                   
                int d = b / f;
                ll c = calc(f, d, a);
                ll e = (c * f - a) / d;
     
                if (e < 0) {
                    e = -e;
                }
       
                assert(e > 0 && c > 0 && c <= 1000000000000 && e <= 1000000000000);
                cout << c << ' ' << d << ' ' << e << ' ' << f << '
    ';        
            }
        } else {
            a /= g, b /= g;
            int t = a / b;
            int c = t + 1, d = 1;
            ll e = b - a % b, f = b;
            cout << c << ' ' << d << ' ' << e << ' ' << f << '
    ';
        }
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        Euler();
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    G. Operating on a Graph

    题意:
    给出一张(n)个点,(m)条边的无向图,现在每个点初始颜色为(i)
    现在有(q)次操作,每次操作选择一个颜色为(i)的集合,并且将其周围的点颜色都染为(i)
    最后问(q)次操作结束过后每个点的颜色。

    思路:
    考虑每个点至多会被染一次色,所以可以直接模拟。
    但模拟涉及到点集的合并,这一点会导致复杂度爆炸。
    然后合并的时候搞个链表其实就行了,因为并不需要随机访问中间某个点,并且链表可以(O(1))合并。

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/20 09:41:10
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 8e5 + 5;
    
    int n, m;
    int f[N];
    list<int> lists[N];
    vector<int> G[N];
    
    void init() {
        for (int i = 0; i < n; i++) {
            f[i] = i;
            G[i].clear();
            lists[i].clear();
            lists[i].push_back(i);
        }
    }
    
    int find(int x) {
        return f[x] == x ? f[x] : f[x] = find(f[x]);
    }
    
    void Union(int x, int y) {
        int fx = find(x), fy = find(y);
        if (fx != fy) {
            f[fy] = fx;
            lists[fx].splice(lists[fx].end(), lists[fy]);
        }
    }
    
    void run() {
        cin >> n >> m;
        init();
        for (int i = 0; i < m; i++) {
            int u, v; 
            cin >> u >> v;
            G[u].push_back(v);
            G[v].push_back(u);
        }
        int q;
        cin >> q;
        while (q--) {
            int o;
            cin >> o;
            if (find(o) != o) continue;
            int size = sz(lists[o]);
            for (int i = 0; i < size; i++) {
                int u = lists[o].front();
                for (auto v : G[u]) {
                    Union(o, v);
                }
                lists[o].pop_front();
            }
        }
        for (int i = 0; i < n; i++) {
            cout << find(i) << ' ';
        }
        cout << '
    ';
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T; while(T--)
        run();
        return 0;
    }
    

    L. Problem L is the Only Lovely Problem

    签到。

    Code
    // Author : heyuhhh
    // Created Time : 2020/07/18 12:01:57
    #include<bits/stdc++.h>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
    void run() {
        string s;
        cin >> s;
        if (s.length() < 6) {
            cout << "ugly" << '
    ';
            return;
        }
        for (int i = 0; i < 6; i++) {
            if (s[i] >= 'A' && s[i] <= 'Z') {
                s[i] = s[i] - 'A' + 'a';
            }
        }
        string t = s.substr(0, 6);
        if (t == "lovely") {
            cout << "lovely" << '
    ';
        } else {
            cout << "ugly" << '
    ';
        }
    }
    int main() {
    #ifdef Local
        freopen("input.in", "r", stdin);
    #endif
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        run();
        return 0;
    }
    
  • 相关阅读:
    b_jd_水坑数量(向外流dfs)
    b_wy_购买商品使得满减最省(01背包)
    b_wy_最优路径(构造树+dfs)
    Redis:List列表相关指令
    Redis:String字符串常用指令
    Redis:linux基本的指令
    Redis:redis-benchmark性能测试/压力测试
    Redis:增大并发量的演进过程
    Kafka的下载安装和测试,及消费端数据中文乱码问题
    Git:常用命令
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/13343902.html
Copyright © 2020-2023  润新知