Codeforces Round #695 (Div. 2)

ABC略

D.

题意:坐标轴上有n个点(1~n),每个点有权值a[i],机器人可以被放置在任何位置,然后每秒钟可以在不越界的前提下往左走或者往右走,并获得当前位置的权值,最多走k秒,求所有可能路径的权值总和.

考虑经过第i号点的路径条数,我们可以先预处理出cnt[i][j]表示i步走到第j号点的方案数,那么经过第i号点的路径条数p[i]就是\sum_{t=0}^{k}cnt[t][i]*cnt[k - t][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";
}                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值