vp Educational Codeforces Round 168 (Rated for Div. 2) A - E

link

A C D,怎么没过 B?我靠,崩溃了牢弟 qwq


A - Strong Password

B - Make Three Regions

这题。。。我居然用 a[2][j] 然后还真只开了 a[2][N] 的大小,结果 cf test 1 多测只输出一个结果,没见过啊,这直接给我干蒙了啊,又是没有调出来,数组空间开小了这种低级错误也能犯

C - Even Positions

一开始以为很不可做,之前是看到字符串匹配之类的就头疼,

不过最后十分钟又看了一下,发现就是简单贪心,总是选择较近的空位配对,两个方向扫一遍,最后三分钟 A 掉了

D - Maximize the Root

树上贪心,(dp?倒是不至于,就是简单的 dfs 加分讨

一种很显然的贪心是,对于一个子树(根节点非叶节点),总是让它的所有点权趋于平均,但是保证子树的根节点比子树中的其他节点的最小值严格不小,这样在向上回溯时能保证非直接儿子不会非法(即点权减小为负数)

对子树跟节点点权 \(a_u\),直接儿子中点权最小值 \(a_v\) 分类讨论

  • \(a_u\geq a_v\),只能直接 \(a_u = a_v\)

  • \(a_u = a_v - 1\),这种平均状态是标准的,不用改变

  • \(a_u < a_v\),要使之趋于平均,\(a_u = a_u + \lfloor \frac{a_v - a_u}{2}\rfloor\),这样就达到要么 \(a_u = a_v\),要么 \(a_u = a_v - 1\) 的效果

当然,根节点是特殊情况,因为它不需要考虑父节点,所以直接 \(a_u = a_u + a_v\)

复杂度 \(O(n)\)

code
#include <bits/stdc++.h>
#define re register int 
#define int long long

using namespace std;
const int N = 2e5 + 10, inf = 1e9 + 10;

struct Edge
{
	int to, next;
}e[N << 1];
int idx, h[N];
int T, n, a[N], in[N];

inline void add(int x, int y)
{
	e[++ idx] = (Edge){y, h[x]};
	h[x] = idx;
}

void dfs(int u, int fa)
{
	int sum = 0, min_son = inf;
	for (re i = h[u]; i; i = e[i].next)
	{
		int v = e[i].to;
		if (v == fa) continue;
		dfs(v, u);
		min_son = min(min_son, a[v]); // 注意是比较更新过后的权值 
//		sum += a[v];
	}
	if (u == 1)
	{
//		cout << "check " << min_son << '\n';
		a[u] += min_son;
		return; 
	}
	else if (in[u] > 1)
	{
		if (a[u] >= min_son) a[u] = min_son;
		else if (a[u] == min_son - 1) a[u] = a[u];
		else 
			a[u] += floor((double)((min_son - a[u]) / 2));
	}
	else return;
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> T;
	while (T --)
	{
		memset(h, 0, sizeof(h)); idx = 0;
		memset(in, 0, sizeof(in));
		
		cin >> n;
		for (re i = 1; i <= n; i ++) cin >> a[i];
		for (re i = 2; i <= n; i ++)
		{
			int x; cin >> x;
			add(x, i), add(i, x);
			in[x] ++, in[i] ++;
		}
		dfs(1, 0);
		
//		cout << a[3] << '\n';
		
		cout << a[1] << '\n';
	}
	return 0;
}

E - Level Up

一开始我以为是个 dp?但是不会推

发现题目已经将一个求解问题转化为判定问题,那考虑往判定方向思考

对于 \(k=x\),发现 \(x\) 越小,对于第 \(i\) 个怪兽而言,它越容易逃跑,因为 \(k\) 越小,玩家期望升级越快,期望等级越比怪物等级高,反之则越不容易逃跑。。。似乎存在二分性

考虑 二分 \(k\)

那我们可以二分一个 \(k\),满足在这个 \(k\) 下,第 \(i\) 个怪物 刚好不逃跑,这样询问时就转化为简单的判定了

考虑一个怪物刚好不逃跑的充要条件就是玩家等级不大于怪物等级,最小化 \(k\)

那么玩家到达第 \(i\) 个位置,至少之前要打过 \(a_i\cdot k\) 个怪兽,即升了 \(a_i\) 级变为 \(a_i + 1>a_i\),这样怪兽就刚好逃跑(似乎刚好逃跑更自然想到,反正也一样二分,反过来就可以了

所以,如果之前打过的怪兽数量 \(query\geq a_i\cdot k\),那么就可以判定怪兽会逃跑

而如何求 \(query\) 呢?注意到我们每次二分出来的值的含义是 刚好使该怪兽不会逃跑的 \(k\),即会打该怪兽

那么就很显然了,每次二分完对 \(k\) 值域加贡献 1,判定时求个前缀即可,考虑 线段树 简单维护

时间复杂度 \(O(n\log^2 n)\)

code
#include <bits/stdc++.h>
#define re register int 
#define lp p << 1
#define rp p << 1 | 1

using namespace std;
typedef long long LL;
const int N = 2e5 + 10;

struct Tree
{
	int l, r, sum;
}t[N << 2];
int n, q, a[N], not_run[N];

inline void build(int p, int l, int r)
{
	t[p].l = l, t[p].r = r;
	if (l == r) return;
	int mid = (l + r) >> 1;
	build(lp, l, mid);
	build(rp, mid + 1, r); 
}

inline void update(int p, int x, int k)
{
	if (t[p].l == x && t[p].r == x) 
	{
		t[p].sum += k;
		return;
	}
	int mid = (t[p].l + t[p].r) >> 1;
	if (x <= mid) update(lp, x, k);
	if (x > mid) update(rp, x, k);
	t[p].sum = t[lp].sum + t[rp].sum;
}

inline LL query(int p, int l, int r)
{
	if (l <= t[p].l && t[p].r <= r) return t[p].sum;
	LL res = 0;
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) res += query(lp, l, r);
	if (r > mid) res += query(rp, l, r);
	
	return res;
}

inline bool check(int x, int k)
{
	return (LL)a[x] * k <= query(1, 1, k);
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> q;
	build(1, 1, n);
	for (re i = 1; i <= n; i ++) cin >> a[i];
	for (re i = 1; i <= n; i ++)
	{
		int l = 1, r = n;
		while (l < r)
		{
			int mid = (l + r) >> 1;
			if (check(i, mid)) l = mid + 1;
			else r = mid;
		}
		update(1, l, 1);
		not_run[i] = l;
	}
	while (q --)
	{
		int x, k; cin >> x >> k;
		cout << (k < not_run[x] ? "No" : "Yes") << '\n';
	}
	return 0;
}

F - Chips on a Line

*2700 的 dp?感觉很不可做,溜了溜了 ~

posted @ 2024-10-24 07:34  Zhang_Wenjie  阅读(31)  评论(0)    收藏  举报