AtCoder Beginner Contest 173 (E-F)

22 篇文章 1 订阅
10 篇文章 0 订阅

E - Multiplication 4 (atcoder.jp)

        (1)题目大意

                给你一个长度为N的序列,要你选择K个数的乘积最大,最后输出模上10^9 + 7后的结果。

         (2)解题思路

                分情况讨论模拟即可。

        (3)代码实现

// Problem: E - Multiplication 4
// Contest: AtCoder - AtCoder Beginner Contest 173
// URL: https://atcoder.jp/contests/abc173/tasks/abc173_e
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include "bits/stdc++.h"
#define rep(i, z, n) for (int i = z; i <= n; i++)
#define per(i, n, z) for (int i = n; i >= z; i--)
#define ll long long
#define db double
#define PII pair<int, int>
#define fi first
#define se second
#define vi vector<int>
#define yes cout << "YES" << endl;
#define no cout << "NO" << endl;
using namespace std;
const int N = 2e5 + 10, mod = 1e9 + 7;
ll a[N];
void solve()
{
    // q1表示正数,q2表示负数
    multiset<ll> q1, q2;
    int n, k;
    cin >> n >> k;
    bool neg = true;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        if (a[i] >= 0)
        {
            q1.insert(a[i]);
            neg = false;
        }
        else
        {
            q2.insert(-a[i]);
        }
    }
    sort(a + 1, a + 1 + n, [&](ll c, ll d) { return c > d; });
    ll mul = 1, t = k;
    if (n == k)
    {

        ll mul = a[1];
        for (int i = 2; i <= k; i++)
        {
            mul = mul * a[i] % mod;
        }
        cout << (mul + mod) % mod << endl;
        return;
    }
    if (k & 1)
    {
        if (neg)
        {
            ll mul = a[1];
            for (int i = 2; i <= k; i++)
            {
                mul = mul * a[i] % mod;
            }
            cout << (mul + mod) % mod << endl;
            return;
        }
        else
        {
            mul *= *(--q1.end());
            q1.erase(--q1.end());
            k--;
            t--;
        }
    }
    while (k > 0 && (q1.size() >= 2 || q2.size() >= 2))
    {
        if (q1.size() >= 2 && q2.size() >= 2)
        {
            auto it1 = (--q1.end());
            auto it2 = (prev(it1));
            auto it3 = (--q2.end());
            auto it4 = (prev(it3));
            if ((*it1) * (*it2) <= (*it3) * (*it4))
            {
                mul = mul * (*it3) % mod;
                mul = mul * (*it4) % mod;
                q2.erase(it3);
                q2.erase(it4);
            }
            else
            {
                mul = mul * (*it1) % mod;
                mul = mul * (*it2) % mod;
                q1.erase(it1);
                q1.erase(it2);
            }
        }
        else if (q1.size() >= 2)
        {
            auto it1 = (--q1.end());
            auto it2 = (prev(it1));
            mul = mul * (*it1) % mod;
            mul = mul * (*it2) % mod;
            q1.erase(it1);
            q1.erase(it2);
        }
        else if (q2.size() >= 2)
        {
            auto it3 = (--q2.end());
            auto it4 = (prev(it3));
            mul = mul * (*it3) % mod;
            mul = mul * (*it4) % mod;
            q2.erase(it3);
            q2.erase(it4);
        }
        else
        {
            auto it1 = q1.begin();
            auto it3 = q2.begin();
            mul = mul * (*it1) % mod;
            mul = mul * (*it3) % mod;
            q1.erase(it1);
            q2.erase(it3);
        }
        k -= 2;
    }
    cout << mul << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int T = 1;
    // cin >> T;
    while (T--)
        solve();
    return 0;
}

F - Intervals on Tree (atcoder.jp)

        (1)题目大意

                给你一个N个点,N-1条边的树,问你树上节点从[L,R]连通块的个数的和。

         (2)解题思路

                考虑用总答案去减去一定不会成功的答案。

                1.总答案:等于从1-n中,第i个答案为i*(i + 1) / 2,相当于一个等差数列和

                2.一定不会成功的答案:对于一条u->v的边,那么u之前的点和v之后的点的答案数量就会减1,总共有u*(n - v+1)个配对,因此总答案减去u*(n - v + 1)

        (3)代码实现

// Problem: F - Intervals on Tree
// Contest: AtCoder - AtCoder Beginner Contest 173
// URL: https://atcoder.jp/contests/abc173/tasks/abc173_f
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include "bits/stdc++.h"
#define rep(i, z, n) for (int i = z; i <= n; i++)
#define per(i, n, z) for (int i = n; i >= z; i--)
#define ll long long
#define db double
#define PII pair<int, int>
#define fi first
#define se second
#define vi vector<int>
#define yes cout << "YES" << endl;
#define no cout << "NO" << endl;
using namespace std;
const int N = 1e5 + 10;
void solve()
{
    ll ans = 0, pre = 0;
    int n;
    cin >> n;
    rep(i, 1, n) ans += 1LL * i * (i + 1) / 2;
    rep(i, 2, n)
    {
        int u, v;
        cin >> u >> v;
        if (u > v)
        {
            swap(u, v);
        }
        ans -= 1LL * u * (n - v + 1);
    }
    cout << ans << endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    int T = 1;
    // cin >> T;
    while (T--)
        solve();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值