1. 程式人生 > 其它 >CF Round#778 C - Alice and the Cake

CF Round#778 C - Alice and the Cake

C - Alice and the Cake

佇列/優先佇列

  1. 記錄每個重量的蛋糕個數

  2. 求出蛋糕的重量之和,看這個重量能否切出這些蛋糕

  3. 把總和放入佇列,如果當前這個重量還有蛋糕,那就不切這個,如果沒有就繼續切

但是這樣廣搜,很多重量其實是切不出來的,但要一直切到 1 才能判斷出來,所以效率很低

因為最多切 \(n-1\) 次,所以每切一次就記錄下來,切夠 \(n - 1\) 次就不切了

如果用優先佇列,維護一個小根堆,小重量很快就可以判斷出能不能切出,這樣效率也很高

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
int n;
ll a[N];

int h;
bool flag;
map<ll, ll> cnt;


int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while(T--)
	{
		flag = false;
		cnt.clear();
		cin >> n;
		ll sum = 0;
		h = 0;
		for (int i = 1; i <= n; i++)
		{
			cin >> a[i];
			cnt[a[i]]++;
			sum += a[i];
		}
		queue<ll> q;
		q.push(sum);
		int t = 0;
		flag = true;
		while(!q.empty())
		{
			ll c = q.front();
			q.pop();
			if (cnt[c] > 0)
				cnt[c]--;
			else
			{
				t++;
				ll a = c / 2, b = c - a;
				//cout << t << " " << a S<< " " << b << " " << cnt[a] << " " << cnt[b] << endl;
				if (a >= 2)
					q.push(a);
				else
					cnt[a]--;
				if (b >= 2)
					q.push(b);
				else
					cnt[b]--;
				if (t == n)
					break;
			}
		}
		for (auto i : cnt)
		{
			if (i.second != 0)
			{
				flag = false;
				//cout << i.first << " " << i.second << endl;
			}
		}
		cout << (flag ? "YES" : "NO") << endl;
	}
	return 0;
}