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;
}