20201003

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;
}
原文地址:https://www.cnblogs.com/scy-fisheep/p/13764242.html