ABC略
D.
题意:坐标轴上有n个点(1~n),每个点有权值a[i],机器人可以被放置在任何位置,然后每秒钟可以在不越界的前提下往左走或者往右走,并获得当前位置的权值,最多走k秒,求所有可能路径的权值总和.
考虑经过第i号点的路径条数,我们可以先预处理出cnt[i][j]表示i步走到第j号点的方案数,那么经过第i号点的路径条数p[i]就是.然后求出原始答案后就可以对修改操作求个贡献就行.
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define ll long long
#define int ll
#define PII pair<int, int>
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int N = 5010, MOD = 1e9 + 7;
//cnt[i][j]表示第i步走到j的方案数
int n, k, q, cnt[N][N], pt[N], a[N];
signed main() {
IOS;
cin >> n >> k >> q;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
cnt[0][i] = 1;
}
for (int i = 1; i <= k; ++i) {
for (int j = 1; j <= n; ++j) {
if (j - 1 >= 1) (cnt[i][j] += cnt[i - 1][j - 1]) %= MOD;
if (j + 1 <= n) (cnt[i][j] += cnt[i - 1][j + 1]) %= MOD;
}
}
int ans = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 0; j <= k; ++j) {
(pt[i] += cnt[j][i] * cnt[k - j][i] % MOD) %= MOD;
}
}
for (int i = 1; i <= n; ++i) (ans += pt[i] * a[i] % MOD) %= MOD;
while (q--) {
int i, x;
cin >> i >> x;
int t = x - a[i];
(ans += t * pt[i]) %= MOD;
(ans += MOD) %= MOD;
cout << ans << "\n";
a[i] = x;
}
}
E.
题意:给定一棵n个节点无根树,求出满足以下条件的节点v个数:若该数以v为根,对于任何从v出发的单条路径,不存在重复的权值.
这道题一看上去不是很难,但是有些细节难以处理.
我们计算合法的点有点难可以反过来做先算出不合法的点.
1.如果一个点其中一个儿子的子树出现与当前的点权相同的点,那么除了那棵儿子的子树外面都不合法.
2.如果在以当前的点为子树外出现与这个点权相同的点,也不合法.
用树上差分+括号序处理即可,最后答案为0的点就是合法的点.
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define ll long long
#define int ll
#define PII pair<int, int>
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int N = 2e5 + 10;
int n, a[N], L[N], R[N], id, s[N];
vector<int> g[N];
map<int, int> cnt, tot;
void dfs(int x, int fa) {
L[x] = ++id;
int t = cnt[a[x]];
++cnt[a[x]];
for (int y : g[x]) {
if (y == fa) continue;
int tmp = cnt[a[x]];
dfs(y, x);
if (cnt[a[x]] > tmp) {
++s[L[1]], --s[L[y]], ++s[R[y] + 1];
}
}
R[x] = id;
if (cnt[a[x]] - t < tot[a[x]]) {
++s[L[x]], --s[R[x] + 1];
}
}
signed main() {
IOS;
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i], ++tot[a[i]];
for (int i = 1; i <= n - 1; ++i) {
int x, y;
cin >> x >> y;
g[x].emplace_back(y), g[y].emplace_back(x);
}
dfs(1, -1);
int ans = 0;
for (int i = 1; i <= n; ++i) {
s[i] += s[i - 1];
if (s[i] == 0) ++ans;
}
cout << ans << "\n";
}