CF-558:部分题目总结

题目链接:http://codeforces.com/contest/1163

A .Eating Soup

sol:在n / 2、n - m、m三个数中取最小值,结果受这三个值限制。但是m == 0的情况需要特判

  • 思维
    #include "bits/stdc++.h"
    using namespace std;
    int main() {
        int n, m;
        scanf("%d%d", &n, &m);
        if (m == 0) {puts("1"); return 0;}
        printf("%d\n", min(n >> 1, min(n - m, m)));
        return 0;
    } 
    View Code

    没有考虑n - m导致了一发wa,而且想了一定时间。好像有点生疏了,哎。

B1 .Cat Party (Easy Edition)

sol:在这一题中u[i]的范围只有10,可以用循环来尝试删除,并判断删除后可否满足题目要求,然后记录;

  • 暴力
    #include "bits/stdc++.h"
    using namespace std;
    const int MAXN = 1e5 + 5;
    int cnt[MAXN];
    int ans, n, k;
    bool check() {
        int k = -1;
        for (int i = 1; i <= 10; i++) {
            if (cnt[i]) {
                if (k == -1) k = cnt[i];
                else if (k != cnt[i]) return false;
            }
        }
        return true;
    }
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &k);
            cnt[k]++;
            /*
             做B2的时候意识到每次删除的要么是只出现一次的数要么是出现次数最多的数 
             所以这个循环可以改成找最大值,然后检查一下最大值和1就行了 
            */ 
            for (int j = 1; j <= 10; j++) {
                if (cnt[j]) {
                    cnt[j]--;
                    if (check()) ans = i;
                    cnt[j]++;
                }
            }
        }
        printf("%d\n", ans);
        return 0;
    }
    View Code

B2 .Cat Party (Hard Edition)

sol:每次删除的数要么是只出现一次的,或者是出现次数最多的。但是暴力找要超时,所以我就用STL里的multiset来了一波优化后的暴力。把思维题做成了暴力;

  • 带优化暴力
    #include "bits/stdc++.h"
    using namespace std;
    const int MAXN = 1e5 + 5;
    multiset<int> st;
    multiset<int>::iterator it;
    int cnt[MAXN];
    int ans, n, k;
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &k);
            if (cnt[k]) {
                it = st.find(cnt[k]);
                st.erase(it);
            }
            cnt[k]++;
            st.insert(cnt[k]);
            // 特判只有一种数字 
            if (st.size() == 1) {
                ans = i;
                continue;
            } 
            if (*st.begin() == 1) {
                st.erase(st.begin());
                if (*st.begin() == *(--st.end())) ans = i;
                st.insert(1);
            }
            it = --st.end();
            k = *it;
            st.erase(it);
            if (*st.begin() == k - 1 && *(--st.end()) == k - 1) ans = i;
            st.insert(k);
        }
        printf("%d\n", ans);
        return 0;
    }
    View Code

    思维果然跟不上队友,只能靠STL这种道具。队友想到了正解

sol:这题的正解是数据结构,用两个数组a和b,a[i]表示数字i出现几次,b[i]表示出现i次的数有几个

  • 数据结构
    #include "bits/stdc++.h"
    using namespace std;
    const int MAXN = 1e5 + 5;
    int a[MAXN], b[MAXN];
    int n, k, mx, ans;
    int main() {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &k);
            b[a[k]]--;
            a[k]++;
            b[a[k]]++;
            mx = max(mx, a[k]);
            if (b[1] == i) ans = i;
            else if (b[i] == 1) ans = i;
            else if (b[1] == 1 && b[mx] * mx == i - 1) ans = i;
            else if ((b[mx - 1] + 1) * (mx - 1) == i - 1) ans = i;
        }
        printf("%d\n", ans);
        return 0;
    }
    View Code
  • 别人同思路的代码
    #include <bits/stdc++.h>
    
    using namespace std;
    int64_t n,x,ans;
    map<int,int>a,b;
    int main()
    {
        cin>>n;
        ans=1;
        for(int i=1;i<=n;i++)
        {
            cin>>x;
            a[x]++;b[a[x]]++;
            if(a[x]*b[a[x]]==i&&i!=n) ans=i+1;
            if(a[x]*b[a[x]]==i-1) ans=i;
        }
        cout<<ans;
    }
    View Code

    看到一份别人的思路差不多的代码,但是他用了map代码很整洁,贴一下。

C .Cat Party (Hard Edition)

sol:用map记录每个角度的边有几条,对于每条边,加一下和自己角度不同的变数。大思路知道,但是有两个地方还有疑惑,还要想一下。期待指教。

  • 几何等一系列杂七杂八东西,还有hash吧,应该算是hash吧
    #include "bits/stdc++.h"
    using namespace std;
    typedef long long LL;
    typedef pair<int, int> PII;
    const int MAXN = 1005;
    map<PII, set<LL> > mp;
    int x[MAXN], y[MAXN];
    LL ans, tot;
    int main() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) 
            scanf("%d%d", &x[i], &y[i]);
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j < i; j++) {
                int x1 = x[i], y1 = y[i];
                int x2 = x[j], y2 = y[j];
                // 这里a和b交换一下就错,不是很理解为什么 
                int a = y2 - y1, b = x2 - x1;
                int g = __gcd(a, b);
                a /= g, b /= g;
                if (a < 0 || (a == 0 && b < 0)) a = -a, b = -b;
                // 这中间换成加号也错,挺奇怪的,这不是一种哈希吗 
                LL c = a * 1LL * x1 - b * 1LL * y1;
                if (mp[{a, b}].count(c) == 0) {
                    tot++;
                    mp[{a, b}].insert(c);
                    ans += tot - mp[{a, b}].size();
                }
            }
        }
        printf("%lld\n", ans);
        return 0;
    }
    View Code

猜你喜欢

转载自www.cnblogs.com/Angel-Demon/p/10846796.html