Codeforces Round #527 (Div. 3) 总结 A B C D1 D2 F

时间:2024-01-16 11:22:20

传送门

A

贪心的取

每个字母n/k次

令r=n%k

让前r个字母各取一次

 #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (int i = a; i <= b; ++i) int t, n, k; int main() {
cin >> t; while (t--) {
cin >> n >> k;
int x = n / k, r = n - x * k;
rep(i, , k) rep(j, , x) {
cout << (char)('a' + i - );
}
rep(i, , r) {
cout << (char)('a' + i - );
}
cout << '\n';
}
return ;
}

B

排序完连续两个比较

证明一下吧:max(a[2] - a[1]), a[4] - a[3]) <= max(a[3] - a[1]), a[4] - a[2]) (后者的间隙大)

 #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (int i = a; i <= b; ++i) const int N = 1e5 + ; int n, a[N]; int main() {
cin >> n; rep(i, , n) {
cin >> a[i];
} sort(a + , a + n + ); int ans = ;
rep(i, , n / ) {
ans += a[i * ] - a[i * - ];
} cout << ans << '\n'; return ;
}

C

题意难理解

找出最长的两个串 判断哪个是最长前缀

f[len]代表着长度为len的前后缀是否被选 用来避免长度为len的两个子串都是前缀或都是后缀的情况

 #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (ll i = a; i <= b; ++i) const int N = ; ll n;
bool f[N];
string s[N]; int main() {
cin >> n; ll m = * n - ; string s1 = "", s2 = "";
rep(i, , m) {
cin >> s[i];
if (s[i].size() > s1.size()) s1 = s[i];
else if (s[i].size() == s1.size()) s2 = s[i];
} ll cnt = ;
rep(i, , m) if (s1.substr(, s[i].size()) == s[i]) {
if (s[i] != s2) cnt++;
} string pre;
if (cnt >= n - && s1.substr(, s1.size() - ) == s2.substr(, s1.size() - )) pre = s1; else pre = s2; rep(i, , m) {
if (pre.substr(, s[i].size()) == s[i] && !f[s[i].size()]) {
cout << 'P';
f[s[i].size()] = ;
}
else cout << 'S';
} return ;
}

D1 D2

两题类似

用一个栈 若当前高度和栈顶一致就弹出 具体判断见代码

 //D1
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (int i = a; i <= b; ++i) const int N = 2e5 + ; int n;
bool a[N];
stack <bool> st; int main() {
scanf("%d", &n); int x;
rep(i, , n) {
scanf("%d", &x);
a[i] = x & ;
} rep(i, , n) {
if(st.empty())
st.push(a[i]);
else if(a[i] == st.top())
st.pop();
else
st.push(a[i]);
} st.size() > ? puts("NO") : puts("YES"); return ;
}
 //D2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, a, b) for (int i = a; i <= b; ++i) int n, mx;
stack <int> s; int main() {
scanf("%d", &n); int x;
rep(i, , n) {
scanf("%d",&x);
mx=max(mx,x);
if (s.empty())
s.push(x);
else if (s.top()==x)
s.pop();
else if (s.top()>=x)
s.push(x);
else {
puts("NO");
return ;
}
} if (!s.size())
puts("YES");
else if (s.size() == && s.top() == mx)
puts("YES");
else
puts("NO"); return ;
}

E

blank

F

初始思路是:维护树上的一堆和乱搞

其实dfs2的操作十分巧妙

1.res -= sum[v] 代表 v子树下的每个点的距离都少了1

2.sum[u] -= sum[v]; 为下一步做准备

3.res += sum[u]; 代表 u子树下(除)的每个点的距离都多了1

4.sum[v]+=sum[u]; dfs2到下一层的时候 (假如边为(v,w)) res+= sum[v](即步骤3)的时候v点外u点子树下的一些点到w的距离也多了1

 #include <bits/stdc++.h>
using namespace std;
typedef long long ll; #define rep(i, a, b) for (int i = a; i <= b; ++i) const int N = 2e5 + ; int n; ll a[N], sum[N], res, ans; vector <int> e[N]; void dfs1(int u, int p = , int d = ) {
res += d * a[u];
sum[u] = a[u];
for (auto v : e[u]) if (v != p) {
dfs1(v, u, d + );
sum[u] += sum[v];
}
} void dfs2(int u, int p = ) {
ans = max(ans, res);
for (auto v : e[u]) if (v != p) {
res -= sum[v];
sum[u] -= sum[v];
res += sum[u];
sum[v] += sum[u]; dfs2(v, u); sum[v] -= sum[u];
res -= sum[u];
sum[u] += sum[v];
res += sum[v];
}
} int main() {
scanf("%d", &n); rep(i, , n) {
scanf("%lld", &a[i]);
} int u, v;
rep(i, , n - ) {
scanf("%d%d", &u, &v);
e[u].push_back(v);
e[v].push_back(u);
} dfs1();
dfs2(); printf("%lld\n", ans); return ;
}