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

Zhang_Wenjie發表於2024-10-24

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?感覺很不可做,溜了溜了 ~

相關文章