Contents

LeetCode Biweekly Contest 91 Tutorial

https://cdn.jsdelivr.net/gh/Oasis7311/halfstack_image@main/blog/202305050913403.png

Q2

https://cdn.jsdelivr.net/gh/Oasis7311/halfstack_image@main/blog/202305050913722.png

Tutorial

An easy dp problem, for dp[i], means how many good string of length i.

Init dp[zero] = 1, dp[one] = 1 (if one == zero, then dp[one] = 2);

So dp[i] = dp[i - zero] + dp[i - one]. After calculate all dp, sum up dp[low] to dp[high].

Accepted Code

https://cdn.jsdelivr.net/gh/Oasis7311/halfstack_image@main/blog/202305050913131.png

class Solution {
public:
	long long dp[100005];

    int countGoodStrings(int low, int high, int zero, int one) {
		memset(dp, 0, sizeof(dp));
		dp[zero]++;   
		dp[one]++;
		for(int i = min(zero, one); i <= high; ++i){
			if(i > zero) dp[i] += dp[i - zero];
			if(i > one) dp[i] += dp[i - one];
			dp[i] %= 1000000007;
		}
		long long ans = 0;
		for(int i = low; i <= high; ++i){
			ans += dp[i];
			ans %= 1000000007;
		}
		return ans;
    }
};

Q3

https://cdn.jsdelivr.net/gh/Oasis7311/halfstack_image@main/blog/202305050913477.png

Tutorial

First, from root 0, bfs all tree to find where bob is. Storage the parent node of every node.

Secondly, from Bob Node, Stroage the time that bob will visit from bob node to root.

Last, from node 0, calculate alice’s maximum income to all leaf.

Accepted Code

https://cdn.jsdelivr.net/gh/Oasis7311/halfstack_image@main/blog/202305050913855.png

class Solution {
public:
	
	int bobVisTime[100005];
    vector<int> to[100005];
	int dp[100005];
	map<int, int> par;
	int res;

    int mostProfitablePath(vector<vector<int>>& edges, int bob, vector<int>& amount) {
		memset(bobVisTime, 0x3f3f3f3f, sizeof(bobVisTime));   
		memset(dp, 0, sizeof(dp));
		res = INT_MIN;

		for(auto i : edges){
			int a = i[0], b = i[1];
			to[a].push_back(b);
			to[b].push_back(a);
		}
		fillBobVisTime(bob);
		
		dfs(0, 0, -1, 0, amount);
		return res;
    }

	void dfs(int a, int t, int p, int ans, const vector<int> &amount){
		//printf("a = %d, t = %d, ans = %d, bobVisTime = %d\n", a, t, ans, bobVisTime[a]);
		if(t == bobVisTime[a]){ //同时到达 
			ans += amount[a] / 2;
		}
		else if(bobVisTime[a] > t){ //alice先到  
			ans += amount[a];
		}
		else{  // bob先到
			ans += 0; 
		}

		for(int i : to[a]){
			if(i != p) dfs(i, t + 1, a, ans, amount);
		}
		if(to[a].size() == 1 && a != 0){ //leaf
			//printf("a = %d\n", a);
			res = max(res, ans);
		}
		return;
	}

    void fillBobVisTime(int b){
		queue<pair<int, int>> q;
		q.push({0, 0});
		while(!q.empty()){
			pair<int, int> t = q.front();
			q.pop();
			for(int i : to[t.first]){
				if(bobVisTime[i] != 0x3f3f3f3f) continue;
				bobVisTime[i] = t.second + 1;
				par[i] = t.first;
				q.push({i, t.second + 1});
			}
		}
		memset(bobVisTime, 0x3f3f3f3f, sizeof(bobVisTime));
		int cnt = 0;
		while(b != 0){
			bobVisTime[b] = cnt++;
			b = par[b];
		}
		bobVisTime[0] = cnt;
		return;
	}
};

Q4

https://halfstack.net/wp-content/uploads/2022/11/image-6-1024x781.png

Tutorial

We define an array sumL of length 1e4. sumL[11] mean the length of all string: “1”, “2”, “3”, …… , “10”, “11”.

So if there is an valid answer, we conbine all the splited string into one string, the length of the string is: message.length + sumL[b] + b * string_of_b.length + b * 3.

If we don’t ignore the last part, make all part’s length equal to limit. The check will be very easy: limit * b == message.length + sumL[b] + b * string_of_b.length + b * 3. If we could find some b(from 1 to 1e4) satisfied this equation, make it to be the answer. But now, we can except the last part of message, whose length can be at most limit. So we just change the equation to be an inequality: limit * b - message.length + sumL[b] + b * string_of_b.length + b * 3 < limit. If we could find a b satisfied this inequality, we find the answer.

Accepted Code

https://cdn.jsdelivr.net/gh/Oasis7311/halfstack_image@main/blog/202305050913185.png

class Solution {
public:
	int sumL[10005];

    vector<string> splitMessage(string message, int limit) {
		memset(sumL, 0, sizeof(sumL));
		for(int i = 1; i <= 10000; ++i){
			sumL[i] = sumL[i - 1] + tos(i).size();
		}
		for(int i = 1; i <= 10000; ++i){
			if(check(i, limit, message.size())){
				return del(i, message, limit);
			}
		}
		return {};
    }
	
	inline vector<string> del(int b, string message, int limit){
		vector<string> res;
		int idx = 0;
		string bs = tos(b);
		int blen = bs.size();
		for(int i = 1; i <= b; ++i){
			string tres = "";
			string as = tos(i);
			int les = limit - 3 - blen - as.size();
			tres = message.substr(idx, les) + "<" + as + "/" + bs + ">";
			idx += les;
			res.push_back(tres);
		}
		return res;
	}

	inline bool check(int b, int limit, int mL){
		if(limit * b - (mL + b * 3 + b * tos(b).size() + sumL[b]) < limit){
			return true;
		}
		return false;
	}

	inline string tos(int n){
		string res = "";
		while(n){
			res += char(n % 10 + '0');
			n /= 10;
		}
		reverse(res.begin(), res.end());
		return res;
	}
};