A
模拟
#include <iostream>
using namespace std;
int main() {
int a1,a2,a3;
cin>>a1>>a2>>a3;
cout<<(abs(a1-a2) + abs(a2-a3) == 0 ? "Yes" : "No")<<'\n';
return 0;
}
B
所有数相同时1种 否则2种 升序或降序
#include <iostream>
#include <unordered_map>
using namespace std;
int main() {
int n,x,mn = 100, mx = 0;
cin>>n;
while (n--)
cin>>x, mn = min(mn, x), mx = max(mx, x);
cout<<(mn == mx ? 1 : 2)<<' '<<mx-mn<<'\n';
return 0;
}
C & D
差分+滑窗统计每个相邻数对计算的次数 然后前缀和还原 并计算
#include <iostream>
using namespace std;
int b[1000005], a[1000005];
int main() {
int n,k;
string s;
cin>>n>>k>>s;
for (int i=1, j=k; j<=n; i++, j++)
b[i]++, b[j]--;
long long ans = 0;
for (int i=1; i<=n; i++)
a[i] = a[i-1]+b[i], ans += a[i]*abs(s[i]-s[i-1]);
cout<<ans<<'\n';
return 0;
}
E
总的陡峭值是固定的 知道一棵子树的陡峭值就可以求出剩余部分的陡峭值
先dfs预处理出每棵子树的陡峭值
然后枚举所有的边(遍历或者再用一次dfs) 计算去掉该条边 子树与剩余部分的陡峭值之差绝对值
#include <iostream>
#include <vector>
using namespace std;
vector<int> g[100005];
long long sub[100005], ans = 9e18;
void dfs(int u, int f) {
for (auto &v: g[u]) {
if (v == f)
continue;
dfs(v, u);
sub[u] += sub[v] + abs(v-u);
}
}
void dfs2(int u, int f) {
for (auto &v: g[u]) {
if (v == f)
continue;
ans = min(ans, abs(sub[v] - (sub[1]-sub[v]-abs(v-u))));
dfs2(v, u);
}
}
int main() {
int n,u,v;
cin>>n;
for (int i=1; i<=n-1; i++)
cin>>u>>v, g[u].push_back(v), g[v].push_back(u);
dfs(1, 0);
dfs2(1, 0);
cout<<ans<<'\n';
return 0;
}
F & G
考虑两个数相邻的概率
利用古典概型和组合数的知识(捆绑法+排列数)可得其概率为:
任意两个数相邻的概率都是2/n 则结果为:
利用排序+前缀和求任意两个数之差绝对值之和
#include <iostream>
#include <algorithm>
using namespace std;
const int M = 1e9+7;
int a[200005];
long long pow(long long a, int k) {
if (k == 0) return 1;
return pow(a*a%M, k/2)*(k%2?a:1)%M;
}
int main() {
int n;
cin>>n;
for (int i=1; i<=n; i++)
cin>>a[i];
sort(a+1, a+1+n);
long long ans = 0, sum = 0;
for (int i=1; i<=n; i++)
ans += (long long)a[i]*(i-1) - sum, ans %= M, sum += a[i];
cout<<ans*2%M*pow(n, M-2)%M<<'\n';
return 0;
}