zoukankan      html  css  js  c++  java
  • 牛客练习赛51

    传送门

    A - abc

    题意:
    给出字符串(s),要求统计(s)中子序列为("abc")的个数。

    思路:
    分别统计一下前缀(a)和后缀(c)的个数即可。

    Code
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MOD = 1e9 + 7;
    const int N = 1e5 + 5;
    ll qp(ll a, ll b) {
        ll ans = 1;
        while(b) {
            if(b & 1) ans = ans * a % MOD;
            a = a * a % MOD;
            b >>= 1;
        }
        return ans;
    }
    char s[N];
    int prea[N], sufc[N];
    
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> s + 1;
        int n = strlen(s + 1);
        for(int i = 1; i <= n; i++) {
            prea[i] = prea[i - 1] + (s[i] == 'a');
        }
        for(int i = n; i >= 1; i--) {
            sufc[i] = sufc[i + 1] + (s[i] == 'c');
        }
        ll ans = 0;
        for(int i = 1; i <= n; i++) {
            if(s[i] == 'b') ans += 1ll * prea[i] * sufc[i];
        }
        cout << ans;
        return 0;
    }
    
    

    B - 子串查询

    题意:
    给出一个字符串(s),之后有多个询问,每个询问会有一个串(t),回答(t)是否为(s)的子序列。

    思路:
    预处理下一位,模拟一下即可。

    Code
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MOD = 1e9 + 7;
    const int N = 1e5 + 5;
    ll qp(ll a, ll b) {
        ll ans = 1;
        while(b) {
            if(b & 1) ans = ans * a % MOD;
            a = a * a % MOD;
            b >>= 1;
        }
        return ans;
    }
    int n, q;
    char s[N];
    char t[55];
    int nxt[N][26], Next[26];
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> n >> q;
        cin >> s + 1;
        for(int i = n; i >= 0; i--) {
            for(int j = 0; j < 26; j++) {
                nxt[i][j] = Next[j];
            }
            Next[s[i] - 'a'] = i;
        }
        for(int i = 1; i <= q; i++) {
            cin >> t + 1;
            int now = 0, len = strlen(t + 1), f = 1;
            for(int j = 1; j <= len; j++) {
                now = nxt[now][t[j] - 'a'];
                if(now == 0) {
                    f = 0; break;
                }
            }
            if(now == 0) cout << "NO" << '
    ';
            else cout << "YES" << '
    ';
        }
        return 0;
    }
    
    

    C - 勾股定理

    数学题,百度一下...

    Code
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MOD = 1e9 + 7;
    const int N = 1e5 + 5;
    ll qp(ll a, ll b) {
        ll ans = 1;
        while(b) {
            if(b & 1) ans = ans * a % MOD;
            a = a * a % MOD;
            b >>= 1;
        }
        return ans;
    }
    ll n;
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> n;
        if(n < 3) {
            cout << -1; return 0;
        }
        if(n & 1) {
            ll b = (n * n - 1) / 2, c = (n * n + 1) / 2;
            cout << b << ' ' << c << '
    ';
        } else {
            ll tmp = n * n / 2;
            if(tmp % 2 != 0) {
                cout << -1;
            } else {
                ll b = (n * n / 2 - 2) / 2, c = (n * n / 2 + 2) / 2;
                cout << b << ' ' << c;
            }
        }
        return 0;
    }
    
    

    D - 羊吃草

    题意:
    现在有一个长度为(400)的数轴,并且存在(n)头羊,每头羊会吃范围在([a_i,b_i])上面的草,每头羊只能吃一个位置上面的草并且一个位置只能被一只羊吃。
    现在有多个询问,对于每个询问会有一个区间([l,r]),询问区间([l,r])上最多有多少只羊在这上面吃草。

    思路:
    显然可以直接二分图最大匹配来搞。
    但有一种很好写的方法:

    • 对于每次的询问,我们每个位置逐一考虑。
    • 当我们考虑到位置(i)时,我们会选择一头羊来进行匹配,这时贪心选择即可,前提是羊吃草的区间包含(i)
    • 具体来说,就是每个羊尽量在最后时刻才吃草,那么我们在前面的时刻都可以选择。
    • (i)位置考虑完了过后,我们要把最晚位置为(i)且还没匹配的羊删去,这是显然的。

    这可以用(multiset)来维护,(erase)某个值时能将那个值全部删除。

    Code
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 405;
    
    multiset <int> s;
    
    int n, q;
    int a[N], b[N];
    
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> n >> q;
        for(int i = 1; i <= n; i++) cin >> a[i];
        for(int i = 1; i <= n; i++) cin >> b[i];
        while(q--) {
            s.clear();
            int l, r; cin >> l >> r;
            int ans = 0;
            for(int i = 1; i <= n; i++) {
                if(a[i] < l && b[i] >= l) s.insert(b[i]);
            }
            for(int i = l; i <= r; i++) {
                for(int j = 1; j <= n; j++) if(i == a[j]) s.insert(b[j]);
                if(s.size()) ++ans, s.erase(s.begin());
                s.erase(i);
            }
            cout << ans << '
    ';
        }
        return 0;
    }
    
    

    E - 数列

    题意:
    现在有长度为(n)的空位,现在我们要往中间填入一些数。
    若存在对于(i>1,a[i]=a[i-1]+1),那么答案会加一。
    先问怎么分配,能使答案最大并且总和不超过(m)

    思路:

    • 注意到肯定是(1,2,cdots,1,cdots)这样来是最优的。
    • 我们将连续递增的几个数统称为“块”,显然,假设最终有(x)块,那么答案就为(n-x)
    • 并且可以发现:块越多,总和越小;否则总和越大,也就是说块的数量是具有单调性的,那么我们就可以二分块的个数。
    • 怎么分配?
    • 注意到若存在:(1,2,cdots,x,1,2,cdots,y)并满足(y>x+1)这种,那么我们将(y)放到(x)后面(变为(x+1)了)是肯定更优的。
    • 所以就平均分配就行了~

    简洁来说,就是二分+均分即可,这些性质也比较显然。

    Code
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 1e5 + 5;
    
    int n, m;
    
    bool chk(int x) {
        int p = n / x;
        int q = n % x;
        ll now = 1ll * q * (p + 1) * (p + 2) / 2;
        now += 1ll * (x - q) * (p + 1) * p / 2;
        return now <= m;
    }
    
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> n >> m;
        int l = 1, r = n + 1, mid;
        while(l < r) {
            mid = (l + r) >> 1;
            if(chk(mid)) r = mid;
            else l = mid + 1;
        }
        int p = n / r, q = n % r;
        for(int i = 1; i <= q; i++) {
            for(int j = 1; j <= p + 1; j++) {
                cout << j << ' ';
            }
        }
        for(int i = 1; i <= r - q; i++) {
            for(int j = 1; j <= p; j++) {
                cout << j << ' ';
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    【转】 Pro Android学习笔记(九一):了解Handler(5):组件生命
    【转】 Pro Android学习笔记(八八):了解Handler(2):什么是Handler
    C# 文字转成声音
    ShowDialog窗体的return问题
    8位、24位、32位图像数据转换
    winform 控件随页面大小进行自适应
    winform下实现pictureBox全屏播放
    SQLServer中求两个字符串的交集(字符串以符号分隔)
    一段四表联查外加字符拼接的sql,留存备查
    使用Nancy搭建简单的Http服务的示例demo
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/11502853.html
Copyright © 2011-2022 走看看