原题链接:
https://codeforces.com/contest/1676
A. Lucky?
题意:给定长度为6由数字组成的字符串问前三个数字的和是否等后三个数字的和。
题解:直接相加比较即可。
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
const int N = 2e5 + 10;
void solve()
{
string s;
cin >> s;
if (s[0] + s[1] + s[2] == s[3] + s[4] + s[5])
cout << "YES" << endl;
else
cout << "NO" << endl;
}
int main()
{
ll t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
B. Equal Candies
题意:每个盒子有一定数量的糖果,问让每个盒子糖果数量一样要吃掉多少糖果。
题解:很明显每个盒子糖果数量是由糖果数最少的决定的,只要记录一下最小值计算一下即可。
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
const int N = 2e5 + 10;
ll n, a[N];
void solve()
{
ll ans = 0, mi = INT_MAX;
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i], mi = min(mi, a[i]), ans += a[i];
//ans记录所有糖果的数量
cout << ans - mi * n << endl;
}
int main()
{
ll t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
C. Most Similar Words
题意:给定一系列长度为n的字符串,找到difference最小的一对字符串,输出它们的difference值。
difference值为每个字符的差距值,如a和b的差距值为1。
题解:范围不大,暴力枚举每一对字符串,记录差距值最小即可。
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
const int N = 2e5 + 10;
ll n;
string str[N];
void solve()
{
ll res, k, mi = INT_MAX;
cin >> n >> k;
for (int i = 1; i <= n; i++) cin >> str[i];
for (int i = 1; i <= n; i++)
{
for (int j = i + 1; j <= n; j++)
{
res = 0;
for (int x = 0; x < k; x++)
{
res += abs(str[i][x] - str[j][x]);
}
mi = min(mi, res);
}
}
cout << mi << endl;
}
int main()
{
ll t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
D. X-Sum
题意:给定一个矩阵,每个位置有一个值,你可以在某个位置(x,y)放置一个棋子,棋子取得的值为四个斜对角方向的所有值(如图),问这个值最大是多少。
题解:没什么好思考的,直接暴力枚举
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
const int N = 2e5 + 10;
ll n, m, mp[500][500];
void solve()
{
ll ans = 0, k, res;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cin >> mp[i][j];
}
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
res = mp[i][j], k = 1;
while (i - k >= 1 && j - k >= 1)
{
res += mp[i - k][j - k];
k++;
}
k = 1;
while (i + k <= n && j + k <= m)
{
res += mp[i + k][j + k];
k++;
}
k = 1;
while (i + k <= n && j - k >= 1)
{
res += mp[i + k][j - k];
k++;
}
k = 1;
while (i - k >= 1 && j + k <= m)
{
res += mp[i - k][j + k];
k++;
}
ans = max(ans, res);
}
}
cout << ans << endl;
}
int main()
{
ll t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
E. Eating Queries
题意:每个糖果有个甜度,多组询问达到k个甜度至少要吃多少个糖果。
题解:对甜度降序排序,求一下前缀和,然后二分即可。
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
const int N = 2e5 + 10;
bool cmp(ll x, ll y) { return x > y; }
ll n, m, a[N], sum[N];
void solve()
{
ll k;
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
sort(a + 1, a + n + 1, cmp);
for (int i = 1; i <= n; i++)
{
sum[i] = sum[i - 1] + a[i];
}
while (m--)
{
cin >> k;
if (sum[n] >= k)
cout << lower_bound(sum + 1, sum + n + 1, k) - sum << endl;
else
cout << -1 << endl;
}
}
int main()
{
ll t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
F. Longest Strike
题意:给定一个数组,求最长的连续的片段且每个数的个数大于k。
题解:map记录个数,去重后循环一遍,按连续片段枚举,记录答案即可,留意一下细节。
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
const int N = 2e5 + 10;
ll n, a[N];
void solve()
{
pair<ll, ll> cnt;
map<ll, ll> p;
set<ll> st;
ll k;
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
p[a[i]] ++;
}
sort(a + 1, a + n + 1);
int r = unique(a + 1, a + n + 1) - a;
cnt.first = -1;
for (int i = 1; i < r; i++)
{
if (st.count(a[i]) || p[a[i]] < k) continue;
int j = 0;
while(p[a[i] + j] >= k)
{
st.insert(a[i] + j);
j++;
}
if (j > cnt.second)
{
cnt.first = i;
cnt.second = j;
}
}
if (cnt.first != -1)
{
cout << a[cnt.first] << " " << a[cnt.first] + cnt.second - 1 << endl;
}
else
{
cout << -1 << endl;
}
}
int main()
{
ll t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
G. White-Black Balanced Subtrees
题意:给定一个树,每个节点是黑色或者白色,问有多少个子树黑色节点数量和白色节点数量一样。
题解:拓扑排序,根据入度从下往上dfs,每次判断一下黑色节点的数量和白色节点的数量是否相同即可。
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
const int N = 2e5 + 10;
ll n, m, rd[4010], f[4010];
string s;
vector<ll> v[4010];
pair<ll, ll> c[4010];
void dfs()
{
for (int p = 1; p <= n; p++)
{
for (int i = 1; i <= n; i++)
{
if (rd[i] == 0 && f[i] == 0)
{
f[i] = 1;
if (c[i].first == c[i].second)
{
m++;//存储答案
}
//更新父节点的值
for (int j = 0; j < v[i].size(); j++)
{
c[v[i][j]].first += c[i].first;
c[v[i][j]].second += c[i].second;
rd[v[i][j]] --;
}
}
}
}
}
void solve()
{
memset(rd, 0, sizeof rd);
memset(f, 0, sizeof f);
memset(c, 0, sizeof c);
m = 0;
ll ans = 0, k;
cin >> n;
for (int i = 1; i <= n; i++) v[i].clear();
for (int i = 1; i < n; i++)
{
cin >> k;
v[i + 1].push_back(k);
rd[k] ++;
}
cin >> s;
for (int i = 0; i < s.size(); i++)
{
if (s[i] == 'W')
{
c[i + 1].first++;
}
else
{
c[i + 1].second++;
}
}
dfs();
cout << m << endl;
}
int main()
{
ll t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
H1. Maximum Crossings (Easy Version)
题意:从1到n每个点都与下面另一个点存在一条边,求交点个数。
题解:考虑一下存在交点的情况。对于两条线段(x1, y1)、(x2, y2),存在交点的情况即x2 >= x1 && y2 <= y1 或者 x2 <= x1 && y2 >= y1。对于每条线段x是单调递增的,即x[n] > x[n - 1]恒成立,那么对于每一个x[n]只需要判断前面有多少线段满足y[n] <= y[n - 1]即可。H1范围比较小可以直接暴力来做。我是每次枚举线段时按y值排序,这样就能二分直接找到满足条件的个数,想着一次性把H1和H2过了,但是还是过不了H2,白搞。
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
const int N = 2e5 + 10;
ll n;
pair<ll, ll> a[200010];
void solve()
{
vector<ll> v;
ll ans = 0, pos;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].second;
a[i].first = i;
}
for (int i = 1; i <= n; i++)
{
if (i != 1)
{
pos = lower_bound(v.begin(), v.end(), a[i].second) - v.begin();
if (pos < v.size() && v[pos] >= a[i].second) ans += v.size() - pos;
}
v.push_back(a[i].second);
sort(v.begin(), v.end());
}
cout << ans << endl;
}
int main()
{
ll t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
H2. Maximum Crossings (Hard Version)
题意:从1到n每个点都与下面另一个点存在一条边,求交点个数。(n的范围从上题的1e3变成了2e5)
题解:其实把问题转化一下就简单了,我们先按y值排序后就是求前面有多少个x的值小于当前这个x,等价于求逆序对的问题,直接套求逆序对lowbit版本,就搞定了。
#include<bits/stdc++.h>
typedef long long int ll;
using namespace std;
const int N = 2e5 + 10;
bool cmp1(pair<ll, ll> x, pair<ll, ll> y) { return (x.second != y.second)? x.second < y.second : x.first > y.first; }
#define lowbit(x) x & -x
ll n, m, c[N];
pair<ll, ll> a[200010];
void modify(ll x, ll d) {
for (int i = x; i <= n; i += lowbit(i)) c[i] += d;
}
ll getsum(ll x) {
ll sum = 0;
for (int i = x; i >= 1; i -= lowbit(i)) sum += c[i];
return sum;
}
void solve()
{
memset(c, 0, sizeof c);
vector<ll> v;
ll ans = 0;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i].second;
a[i].first = i;
}
sort(a + 1, a + n + 1, cmp1);
for (int i = 1; i <= n; i++)
{
v.push_back(a[i].first);
}
for (int i = 0; i < v.size(); i++) {
ans += getsum(n) - getsum(v[i]);
modify(v[i], 1);
}
cout << ans << endl;
}
int main()
{
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll t;
cin >> t;
while (t--)
{
solve();
}
return 0;
}
标签:return,790,H2,题解,ll,long,int,while,solve
From: https://www.cnblogs.com/wockcow/p/16918561.html