T1
首先,这道题在考场上完全没去想正解是啥,但是可以明确的一点是这道题不难,考场上就想写一个暴力加a,b两点,期望得分:20。实际得分:20。
虽然拿到期望得分,但是这道题的正解却十分的简单,是(GG)最熟悉的贪心,这样可以拿到95分,再用线段树维护一下即可A掉。
#include<bits/stdc++.h>
#define ls (d << 1)
#define rs (d << 1 | 1)
using namespace std;
typedef long long LL;
const int N = 500005;
int n, a[N];
LL k;
char str[N];
struct tree {
int s, mn;
} t[N * 4];
void update(int d) {
t[d].s = t[ls].s + t[rs].s;
if(a[t[ls].mn] <= a[t[rs].mn] ) {
t[d].mn= t[ls].mn;
} else {
t[d].mn = t[rs].mn;
}
}
void build(int d, int l, int r) {
if (l == r) {
t[d].s = 1;
t[d].mn = l;
return;
}
int mid = (l + r) / 2;
build(ls, l, mid);
build(rs, mid + 1, r);
update(d);
}
int find(int d, int l, int r, int s) {
if (l == r) return l;
if (t[d].s == s) return t[d].mn;
int mid = (l + r) / 2;
if (t[ls].s >= s) return find(ls, l, mid, s);
int u = find(ls, l, r, t[ls].s), v = find(rs, mid + 1, r, s - t[ls].s);
return a[u] <= a[v] ? u : v;
}
int get_rank(int d, int l, int r, int x) {
if (r <= x) return t[d].s;
int mid = (l + r) / 2;
if (x <= mid) return get_rank(ls, l, mid, x);
else return t[ls].s + get_rank(rs, mid + 1, r, x);
}
void del(int d, int l, int r, int x) {
if (l == r) {
t[d].s = t[d].mn = 0;
return;
}
int mid = (l + r) / 2;
if (x <= mid) del(ls, l, mid, x);
else del(rs, mid + 1, r, x);
update(d);
}
int main() {
// freopen("escape.in", "r", stdin);
// freopen("escape.out", "w", stdout);
scanf("%d%lld", &n, &k);
scanf("%s", str + 1);
for (int i = 1; i <= n; i++) a[i] = str[i] - 'a';
a[0] = 100;
build(1, 1, n);
for (int i = 1; i <= n; i++) {
int s = min((LL)n - i + 1, k + 1), pos = find(1, 1, n, s);
k -= get_rank(1, 1, n, pos) - 1;
del(1, 1, n, pos);
putchar(str[pos]);
}
return 0;
}
T2
用(DFS)遍历整棵树,统计合法答案。
期望得分:30分
正解:
先通过递推求出从每个点出发,海拔单调下降的路径数量。对于每个点(x),设从(x)出发,到每棵子
树中的海拔单调下降的路径数量分别为(s_1, · · · , s_k),那么以该点为海拔最高点的合法路径数量为
[left(sum_{i=1}^ks_i
ight)^2-sum_{i=1}^ks_i^2
]
将所有点的贡献相加就是答案。
时间复杂度(~O(n)~)。期望得分:100
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 300005;
int n, f[N];
vector<int> e[N];
int main() {
// freopen("ride.in", "r", stdin);
// freopen("ride.out", "w", stdout);
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int x, y;
scanf("%d%d", &x, &y);
e[x].push_back(y);
e[y].push_back(x);
}
LL ans = 0;
for (int i = 1; i <= n; i++) {
for (int x=0;x< e[i].size();x++) if (e[i][x] < i) f[i] += f[e[i][x]] + 1;
for (int x=0;x< e[i].size();x++) if (e[i][x] < i) ans += (LL)(f[i] - f[e[i][x]] - 1) * (f[e[i][x]] + 1);
}
printf("%lld
", ans);
return 0;
}