A. Lucky?
题意:给你 T 个由六个数字组成的票据,如果票据的前三个数字之和和后三个数字之和相等,则输出 YES ,否则输出 NO
思路:模拟即可
string s;
cin >> s;
int l= 0 , r = 0;
l += s[0] - '0';
l += s[1]- '0';
l += s[2]- '0';
r += s[3]- '0';
r += s[4]- '0';
r += s[5]- '0';
if(l == r)cout <<"YES\n";
else cout <<"NO\n";
B. Equal Candies
题意:有 n 盒糖,第 i 盒糖中有 ai 颗糖。你有 n 个朋友,你想给每个朋友发一盒糖。但是每盒糖的数量可能不一样,所以你想要吃掉一些糖,使得每盒糖中糖数相等。
注意:你可以在不同的盒子中吃掉不同数量的糖(可以不吃),但不能向任何盒子中加糖。
问你最少吃掉多少颗糖,才能完成目标。
思路:注意到给糖的数量仅收到最小值的影响,所以遍历一下找到以后开始计入答案即可
int n;
cin >> n;
for(int i = 1;i<=n;i++)cin >>q[i];
int min_val = INF;
for(int i = 1;i<=n;i++)min_val = min(q[i],min_val);
LL ans = 0;
for(int i = 1;i<=n;i++)ans += q[i] - min_val;
cout << ans << endl;
C. Most Similar Words
题意:你有 n 个长度为 m 的单词,第 i 个单词是 si。在一个操作中,你可以把任何一个单词的任何一个位置上的字母改成它相邻的字母,我们定义si 与 sj 的差异度为使 si=sj 所需的操作次数,如 "best" 与 "cost" 差异度为 1+10+0+0=11。
你要找到 si 与 sj(满足 i<j)的差异度的最小值,也就是每一对单词差异度的最小值。
思路:注意到题目要求找到没两个单词之间最小的差异度,所以直接遍历一下找最小值即可
int n , m;
cin >> n >> m;
vector<string> alls(n);
for(int i = 0;i<n;i++)cin >>alls[i];
vector<int> ans;
for(int i = 0;i<n;i++){
int temp = 0;
for(int j = i+1;j<n;j++){
for(int k = 0;k<m;k++){
temp += abs(alls[i][k] - alls[j][k]);
}
ans.push_back(temp);
temp = 0;
}
}
sort(ans.begin(),ans.end());
cout << ans[0]<<endl;
D. X-Sum
题意:有一个 n×m 的国际象棋盘 a,(i,j) 上有一个非负整数 aij。
你要在上面放一个象,问它能攻击到的点上的非负整数和最大是多少。
(象走斜线,无距离限制,可以参考样例解释)
注意:象所在的点也是它能攻击到的点。
思路:二维平面过某点两条对角线上元素最大值,给过当前点的两条对角线计入元素,查询的时候直接查询两条对角线贡献再去重一次,即有O1的时间复杂度
int t;
cin >> t;
while(t--)
{
int n , m;
cin >> n >> m;
vector<int> l(n+1,0),r(n+1,0);
int ans = 0;
for(int i = 1;i <= n;++i)
for(int j = 1;j <= m;++j)
cin >> a[i][j];
l[i + j] += a[i][j], r[i - j + m] += a[i][j];
for(int i = 1, t;i <= n;++i)
for(int j = 1;j <= m;++j)
if((t = l[i + j] + r[i - j + m] - a[i][j]) > ans) ans = t;
cout << ans <<endl;
}
return 0;
E. Eating Queries
题意:
有 n 颗糖,吃第 i 颗糖可以得到 ai 的糖分。
有 q 次询问,每次询问最少吃多少颗糖可以得到不小于 x 的糖分,无解输出 -1。
思路:为了找到最小的次数,肯定希望先吃大的。从大到小排序以后记录一下前缀和,然后查询的时候使用二分即可,超出总和则答案为-1
int n , q;
cin >> n >>q;
LL sum = 0;
vector<LL> a(n);
for(int i = 0;i<n;i++){
cin >> a[i];
sum += a[i];
}
vector<pair<LL,LL>> alls;
sort(a.begin(),a.end(),greater<LL>());
LL temp = 0;
for(int i = 0;i<n;i++){
temp += a[i];
alls.push_back({temp,i+1});
}
while(q--){
LL x;
cin >>x;
if( x > sum){
cout <<"-1" << endl;
}
else{
LL l = 0, r = n-1;
while( l < r){
LL mid = l + r >>1;
if(alls[mid].first >= x) r = mid;
else l = mid + 1;
}
cout << alls[l].second << endl;
}
}
F. Longest Strike
题意:
给你一个长度为 n 的序列 a 和一个整数 k,你要求一个区间 [l,r] 满足:
对于任何整数 x∈[l,r],x 在 a 中的出现次数不少于 k 次。
最大化 r−l。
思路:观察到题目让我们找一个其中任意元素在数列a中出现不少于 k 次的区间。而不是在从 l~r的每个数在a中出现k次。所以数列排序并没有影响,那么可以将这个数列排序,把数组中出现次数大于 k 的数按顺序拎出来
那么直接开一个map记录出现次数 >=k的,然后找最长连续区间即可
// Code Start Here
int t;
cin >> t;
while(t--){
int n , k;
cin >> n >> k;
vector<int> a(n);
map<int,int> mp;
for(int i = 0;i<n;i++){
cin >> a[i];
mp[a[i]]++;
}
deque<int> f;
for(PII i : mp){
if(i.se >= k)f.pb(i.fi);
}
vector<array<int,3>> ans;
if(f.empty())cout <<"-1\n";
else{
while(!f.empty()){
int l = f.front();
int r;
int cnt = 0;
int last = f.front() - 1;
while(!f.empty() && f.front() == last+1){
last = f.front();
r = last;
cnt++;
f.ppf();
}
ans.pb({cnt , l , r});
}
sort(all(ans),[&](array<int,3>a,array<int,3>b){
return a[0] > b[0];
});
cout << ans[0][1] <<" " << ans[0][2] << endl;
}
}
G. White-Black Balanced Subtrees
题意:给定一棵 n 个结点的树,根结点是 1,每个结点是黑色或白色的。如果一棵树中黑色结点与白色结点数量相同,那么这棵树是“平衡的"。问这棵 n 个结点的树有多少棵“平衡的”子树。
思路:从根开始往下遍历每个孩子,到尾部计算是否平衡,这里可以让黑白变成 - 1 1,和为0即可平衡
变形的dfs,想到如何建立平衡的模型即可
vector<int> v[N];
int color[N];
int ans;
int n, fa;
char c;
int dfs(int now) {
int sum = color[now];
for (int i = 0; i < v[now].size(); i++) {
sum += dfs(v[now][i]);
}
if (sum == 0) ans++;
return sum;
}
void solve() {
cin >> n;
for (int i = 1; i <= n; i++) v[i].clear();
ans = 0;
for (int i = 2; i <= n; i++) {
cin >> fa;
v[fa].push_back(i);
}
for (int i = 1; i <= n; i++) {
cin >> c;
if (c == 'W') color[i] = -1;
else color[i] = 1;
}
dfs(1);
cout << ans << endl;
}
H1,H2:
题意:
一个终端是一排 n 个连接在一起的相等的线段,有两个终端,一上一下。
有一个数组 ai,代表从上面的终端中第 i 条线段,到下面的终端中第 ai 条线段,有一条连线。
问这些连线最多有几个交点。
H1:N <1000,
H2:N<1e5+10
思路:考虑什么时候会产生交点,我们设第一条线段上面为 x1,下面为y1,第二条为x2,y2,那么只有两种情况会产生交点
1:x1 < x2 && y1 > y2
2:x1 > x2 && y1 < y2
显然这是一个逆序对的变形,使用归并排序即可
由于H1数据范围较小,可以使用On^2的时间复杂度暴力便利,此处不给出代码
int test_case;
cin >> test_case;
while (test_case--){
int n;cin >> n;
int ans = 0;
for (int i = 1; i <= n; i++)cin >> a[i];
auto merge_sort = [&](auto merge_sort,int l ,int r)->void{
if (l == r) return ;
int mid = l + r >> 1;
merge_sort(merge_sort,l, mid), merge_sort(merge_sort,mid + 1, r);
for (int i = l, j = mid + 1; j <= r; j++){
while (i <= mid && a[i] < a[j]) i++;
ans += mid - i + 1;
}
int pl = l, pr = mid + 1, p = l;
while (pl <= mid && pr <= r)t[p++] = a[pl] < a[pr] ? a[pl++] : a[pr++];
while (pl <= mid) t[p++] = a[pl++];
while (pr <= r) t[p++] = a[pr++];
for (int i = l; i <= r; i++) a[i] = t[i];
};
merge_sort(merge_sort,1, n);
cout << ans << endl;
}
1171

被折叠的 条评论
为什么被折叠?



