讨论/题目交流/🏆 第 168 场力扣周赛/
🏆 第 168 场力扣周赛

欢迎小伙伴们在这里交流分享你的参赛心得以及体验。【前往竞赛

image.png

3 分 - 统计位数为偶数的数字
4 分 - 划分数组为连续数字的集合
6 分 - 子串的最大出现次数
7 分 - 你能从盒子里获得的最大糖果数

共 16 个回复

题解 (LeetCode 竞赛题真是越来越难了,今天居然翻车了)

第一题:统计位数为偶数的数字

数数位。可以转字符串做,也可以直接做。

class Solution {
public:
    int findNumbers(vector<int>& nums) {
        int ret=0;
        for (auto&i:nums){
            int tmp=0;
            while (i){
                ++tmp;
                i/=10;
            }
            if (tmp%2==0)++ret;
        }
        return ret;
    }
};

第二题:划分数组为连续数字的集合

贪心。假设当前还有数字序列 [y,x1,x2,x3,x4,...,xn][y,x_1,x_2,x_3,x_4,...,x_n] ,其中 yy 是序列中最小的数字,那么如果真的有解,就必须出现序列 [y,y+1,y+2,...,y+k1][y,y+1,y+2,...,y+k-1] ,否则 yy 就无法匹配了。所以每次贪心选择最小的数字序列减掉就行。
用map维护或者哈希表维护一下即可。

class Solution {
public:
    bool isPossibleDivide(vector<int>& nums, int k) {
        map<int,int> mmp;
        int cur=0x3f3f3f3f;
        for (auto&i:nums){
            mmp[i]++;
            cur=min(cur,i);
        }
        if (nums.size()%k!=0) return false;
        int rua=nums.size()/k;
        for (int i=0;i<rua;++i){
            for (int j=0;j<k;++j){
                if (mmp[cur+j]<=0) return false;
                --mmp[cur+j];
            }
            cur=0x3f3f3f3f;
            for (auto &i:mmp){
                if (i.second>0) cur=min(cur,i.first);
            }
        }
        return true;
    }
};

第三题:子串的最大出现次数

贪心,因为只要返回任意一个符合要求的字串。我们知道,如果一个长度为 xx ( xminSizex \ge minSize )的子串符合要求,那么这个子串的长度为 minSizeminSize 的子串也全部符合要求,并且这样的子串出现次数只可能更多不可能更少。因此, maxSizemaxSize 除了用来判断 minSizemaxSizeminSize \leq maxSize 以外没有任何作用。
然后就剩下暴力了, O(n)O\left(n\right) 扫一下整个字符串长度为 minSizeminSize 的子串,同时维护当前26个字符出现的次数即可。需要一点实现技巧。

class Solution {
public:
    int maxFreq(string s, int x, int len, int maxSize) {
        if (len>maxSize) return 0;
        int n=s.length();
        map<string,int> mmp;
        map<char,int> cur;
        for (int i=0;i<len;++i){
            cur[s[i]]++;
        }
        if (cur.size()<=x){
            mmp[s.substr(0,len)]++;
        }
        for (int i=0;i+len<n;++i){
            if (cur[s[i]]==1) cur.erase(s[i]);
            else --cur[s[i]];
            ++cur[s[i+len]];
            if (cur.size()<=x) ++mmp[s.substr(i+1,len)];
        }
        int ans=0;
        for (auto &i:mmp){
            ans=max(ans,i.second);
        }
        return ans;
    }
};

第四题:你能从盒子里获得的最大糖果数

模拟。首先需要想明白的是,由于所有的状态都是给定的(比如不存在需要决策钥匙开哪个盒子因为钥匙只能开对应的盒子,也不存在箱子中糖果个数为负的的情况),答案其实是唯一的。

开一些数据结构:

  • 开一个数组(vector)记录箱子是否被拥有;
  • 开一个数组(vector)记录箱子是否已经被使用了;
  • 开一个队列(queue)记录当前待检查的箱子(检查其中新的箱子,糖果和钥匙)

然后每次取一个检查队列中的箱子进行检查:

  • 拿到箱子就立刻标记箱子被拥有
  • 拿到钥匙就立刻把对应锁着的箱子解锁
  • 将拥有的,解锁的,未被使用的箱子加入队列准备新一轮的检查

以此往复将将所有能打开的箱子全部打开,得到的糖果必然是最多的。

class Solution {
public:
    int maxCandies(vector<int>& open, vector<int>& x, vector<vector<int>>& keys,
                   vector<vector<int>>& boxes, vector<int>& initBoxes) {
        queue<int> que;
        bool vis[1010];
        bool has[1010];
        memset(vis,false,sizeof(vis));
        memset(has,false,sizeof(has));
        for (auto&i:initBoxes){
            if (open[i]==1){
                vis[i]=true;
                que.push(i);
            }
            else{
                has[i]=true;
            }
        }
        int ans=0;
        while (!que.empty()){
            int cur=que.front();que.pop();
            ans+=x[cur];
            for (auto&i:boxes[cur]){
                has[i]=true;
                if (has[i]&&open[i]&&!vis[i]){
                    vis[i]=true;
                    que.push(i);
                }
            }
            for (auto&i:keys[cur]){
                open[i]=1;
                if (open[i]&&has[i]&&!vis[i]){
                    vis[i]=true;
                    que.push(i);
                }
            }
        }
        return ans;
    }
};

题外话:
题目给的样例都是这样的,简直反人类好不好!!比如第四题

输入:status = [1,1,1], candies = [2,3,2], keys = [[],[],[]], containedBoxes = [[],[],[]], initialBoxes = [2,1,0]
输出:7

既然有这么长的样例,为什么不直接给可以复制使用的格式

[1,1,1]
[2,3,2]
[[],[],[]]
[[],[],[]]
[2,1,0]

要是C++玩家能得到{}而非[]就更好了,这样就可以直接初始化vector了

{1,1,1}
{2,3,2}
{{},{},{}}
{{},{},{}}
{2,1,0}

或者自定义输入的时候能选择题目样例也很棒啊……(逃

填入样例1
填入样例2
填入样例3

翻车了,这次前五十都没进……丢人

7

第一题:

题解略

class Solution {
public:
    int cal(int n) {
        int ret = 0;
        while (n != 0) {
            ret ++;
            n /= 10;
        }
        return ret;
    }
    int findNumbers(vector<int>& nums) {
        int ret = 0;
        for (auto& x: nums) {
            if (cal(x) % 2 == 0) {
                ret++;
            }
        }
        return ret;
    }
};

第二题:

先统计每个数分别有多少个,然后每一轮,从最小的数开始,取连续k个,如果中间的某个数的个数为0,直接返回false,这样直接把所有的数全取完,返回true

class Solution {
public:
    bool isPossibleDivide(vector<int>& nums, int k) {
        map<int, int> count;
        for (auto& x: nums) {
            count[x]++;
        }
        while (count.size() > 0) {
            int x = count.begin()->first;
            for (int i = 0;i < k;i++) {
                if (count.find(x) == count.end()) {
                    return false;
                }
                count[x]--;
                if (count[x] == 0) {
                    count.erase(count.find(x));
                }
                x++;
            }
        }
        return true;
    }
};

第三题:

注意条件,1 <= minSize <= maxSize <= min(26, s.length)
假设s两个子串,p和t,并且p是t的子串,len(p) < len(t)
那么

  1. 如果p满足“子串中不同字母的数目必须小于等于maxLetters”,那么t不一定满足
  2. 如果p不满足“子串中不同字母的数目必须小于等于maxLetters”,那么t一定不满足
  3. p在s出现的次数,肯定不小于t在s出现的次数

因此,我们只需要判断s中所有长度为minSize的子串是否满足“子串中不同字母的数目必须小于等于maxLetters”,再统计最大的次数即可

还有一个条件。。。minSize <= min(26, s.length),也就是minSize最大才26。比赛中看成minSize <= max(26, s.length),导致整了1个小时才打出来,大掉分,悲剧啊。。。。

class Solution {
public:
    int maxFreq(string s, int maxLetters, int minSize, int maxSize) {
        map<string, int> count;
        for (int i = 0;i + minSize - 1 < s.size();i++) {
            string p = s.substr(i, minSize);
            vector<bool> bit(26, false);
            for (auto& c: p) {
                bit[c - 'a'] = true;
            }
            int l = 0;
            for (int i = 0;i < 26;i++) {
                if (bit[i]) {
                    l++;
                }
            }
            if (l <= maxLetters) {
                count[p]++;
            }
        }
        int ret = 0;
        for (auto& it: count) {
            ret = max(ret, it.second);
        }
        return ret;
    }
};

第四题:

模拟题,每一轮寻找没被访问过的,可见的,并且开着的,或者关着有钥匙的箱子,访问,吃糖果,把里面的箱子拿出来,把钥匙拿出来。。。直到没有箱子可以被访问

class Solution {
public:
    int maxCandies(vector<int>& status, vector<int>& candies, vector<vector<int>>& keys, vector<vector<int>>& containedBoxes, vector<int>& initialBoxes) {
        int n = status.size();
        vector<bool> visited(n, false);
        vector<bool> watch(n, false);
        vector<bool> hasKey(n, false);
        
        for (auto& x: initialBoxes) {
            watch[x] = true;
        }
        int ret = 0;
        while (1) {
            int find = -1;
            for (int i = 0;i < n;i++) {
                if (!watch[i] || visited[i]) {
                    continue;
                }
                if (status[i] == 0 && !hasKey[i]) {
                    continue;
                }
                find = i;
                break;
            }
            if (find == -1) {
                break;
            }
            visited[find] = true;
            ret += candies[find];
            for (auto& x: keys[find]) {
                hasKey[x] = true;
            }
            for (auto& x: containedBoxes[find]) {
                watch[x] = true;
            }
        }
        return ret;
    }
};
6

今天的比赛整体比较简单,但是第三题少了个 break TLE 了 7 次,尴尬。 ̄□ ̄||


5291. 统计位数为偶数的数字

数字转字符串,统计一下长度出答案

class Solution:
    def findNumbers(self, nums: List[int]) -> int:
        res = 0
        for n in nums:
            nn = str(n)
            if len(nn) % 2 == 0:
                res += 1
        return res        

5292. 划分数组为连续数字的集合

先做一次计数,然后用一个小顶堆依次遍历,一次拿出 k 个。如果计数仍然 > 0 就再放回去。

class Solution:
    def isPossibleDivide(self, nums: List[int], k: int) -> bool:
        if len(nums) % k != 0:
            return False
        cnt = dict(collections.Counter(nums))
        cnts = sorted(cnt.items(), key=lambda item: item[0])
        from queue import PriorityQueue as PQ
        pq = PQ()
        for kkk in cnt.keys():
            pq.put(kkk)    
        #print(pq.queue)    
        while len(pq.queue):
            curs = []
            for _ in range(k):
                if len(pq.queue) == 0:
                    return False
                x = pq.get()
                if len(curs) != 0 and curs[-1] != x - 1:
                    return False
                curs.append(x)
            for cc in curs:
                cnt_cc = cnt.get(cc, 0)
                cnt[cc] = cnt_cc - 1
                if cnt_cc - 1 > 0:
                    pq.put(cc)
            #print("curs", curs)        
            #print("pq", pq.queue)        
        return True      

5293. 子串的最大出现次数

看很多人用的滑窗,其实都可以。我直接遍历起始点和长度,然后直接插入字典做计数就可以了。注意两个减枝:

  1. 某个起点具有最小长度时就不需要再往下统计了,一个可能子串越少,数量越多;
  2. 根据题意,计数种类 > maxLetters,也就不用再统计了;
class Solution:
    def maxFreq(self, s: str, maxLetters: int, minSize: int, maxSize: int) -> int:
        ctt = {}
        for i in range(len(s) - minSize + 1):
            for ll in range(minSize, maxSize + 1):
                sub = s[i: i + ll]
                cnt = collections.Counter(sub)
                if len(cnt) > maxLetters:
                    break
                ctt[sub] = ctt.get(sub, 0) + 1    
                break
        return max([val for k, val in ctt.items()]) if len(ctt) > 0 else 0

5294. 你能从盒子里获得的最大糖果数

这道题目,其实就是一道简单 BFS,根本算不上 Hard!!hasBoxhasKey 看成两个条件,已经打开的其实就等价于有钥匙的。然后做一个任务队列,每开一个盒子,查一下最新状态,继续追加到队列里循环处理即可。没有什么坑。

搜索的题目我一率用 cpp 写,别问我为什么! 👀

class Solution {
public:
    int maxCandies(vector<int>& status, vector<int>& candies, vector<vector<int>>& keys, vector<vector<int>>& containedBoxes, vector<int>& initialBoxes) {
        map<int, int> hasKey;
        map<int, int> hasBox;
        int res = 0;
        for (int i = 0; i < status.size(); ++ i) {
            if (status[i] == 1) {
                hasKey[i] = 1;
            }
        }
        for (int i = 0; i < initialBoxes.size(); ++ i) {
            int b = initialBoxes[i];
            hasBox[b] = 1;
        }
        queue<int> que;
        map<int, int> isFinished;
        map<int, int> :: iterator it = hasKey.begin();
        for(; it != hasKey.end(); it ++) {
            if (hasBox[it -> first]) {
                que.push(it -> first);
            }
        }
        while (!que.empty()) {
            int cur = que.front();
            que.pop();
            if (isFinished[cur]) continue;
            if (hasKey[cur] && hasBox[cur]) {
                res += candies[cur];
                isFinished[cur] = 1;
                for (int i = 0; i < keys[cur].size(); ++ i) {
                    hasKey[keys[cur][i]] = 1;
                }
                for (int i = 0; i < containedBoxes[cur].size(); ++ i) {
                    hasBox[containedBoxes[cur][i]] = 1;
                }
                for (it = hasKey.begin(); it != hasKey.end(); it ++) {
                    if (!isFinished[it -> first] && hasKey[it -> first] && hasBox[it -> first]) {
                        que.push(it -> first);
                    }
                }
            }
            
        }
        return res;
    }
};


最后,如果大家对移动端和刷算法题感兴趣,可以微信关注我的技术公众号。

image.png

4

第三题竟然把所有子串丢到unordered_map里就过了。浪费了一个小时...

2

第一次做完4道题,果然今天的题比较简单...

2

第一题

直接依次统计位数就行了,没有边界条件处理

class Solution {
public:
    int findNumbers(vector<int>& nums) {
        int ans = 0;
        
        for(auto x:nums) {
            int cnt = 0;
            while(x) {
                cnt ++;
                x/=10;
            }
            if(cnt%2==0) ans++;
        }
        return ans;
    }
};

第二题

贪心,首先用hashhash表统计数字出现的次数,可以理解为一一段段的线段:
对于线段的两个端点,在删除的时候也一定是长度为k的线段的头尾的形式进行删除的。否则将不可能成功删除。
代码:

class Solution {
public:
    bool isPossibleDivide(vector<int>& nums, int _k) {
        map<int,int> h;
        for(auto x:nums) h[x]++;
        
        for(auto it = h.begin() ; it != h.end() ; ++it) {
            auto [k,v] = *it;
            if(v == 0) continue;
            if(v < 0) return false;
            for(int i = 0 ; i < _k ; i++) {
                h[k+i]-=v;
            }
        }
        return true;
    }
};

第三题

贪心+滑窗,在大于minlen的情况下,长度越小越好。
采用滑动窗口判断长度为minlen的子串中的字母出现个数。然后选取最大的一个。

class Solution {
public:
    int maxFreq(string s, int maxLetters, int minSize, int maxSize) {
        unordered_map<string,int> h;
        unordered_map<char,int> h2;
        int j = 0;
        int ans = 0;
        for(int i = 0 ; i < s.size() ; i++) {
            h2[s[i]]++;
            if(i-minSize+1>0) {
                if(--h2[s[j]] == 0) h2.erase(s[j]);
                j++;
            }

            if(i>=minSize-1 && h2.size() <= maxLetters)
                ans = max(ans,++h[s.substr(i-minSize+1,minSize)]);
        }
        return ans;
    }
};

第四题

不断地重复:开箱子->拿钥匙/糖果,这个循环就可以了,箱子肯定是越开越少的。O(n2)O(n^2)不超时。

class Solution {
public:
    int maxCandies(vector<int>& status, vector<int>& candies, vector<vector<int>>& keys, vector<vector<int>>& containedBoxes, vector<int>& initialBoxes) {
        int n = status.size();
        vector<bool> ks(n,false), bx(n,false), st(n,false);
        for(auto x:initialBoxes) {
            bx[x] = true;
            for(auto y:keys[x])
                ks[y] = true;
        }
        for(int i = 0 ; i < n ; i ++)
            if(status[i]) ks[i] = true;
        
        int ans = 0;
        bool flag = true;
        
        while(flag) {
            flag = false;
            
            for(int i = 0 ; i < n ; i++) {
                if(st[i]) continue;
                if(ks[i] && bx[i]) {
                    ans += candies[i];
                    for(auto x:keys[i]) ks[x] = true;
                    for(auto x:containedBoxes[i]) bx[x] = true;
                    flag = true;
                    st[i] = true;

                }
            }
        }
        return ans;
    }
};
2

题解

统计位数为偶数的数字

转成字符串算size就好了。

int findNumbers(vector<int>& nums) 
{
	int ans = 0;
	for (auto n : nums)
	{
		string str = to_string(n);
		ans += ((str.size() % 2) == 0);
	}
	return ans;
}

划分数组为连续数字的集合

  1. 把数字全都丢到map里,统计数量。
  2. 遍历map。
  3. 取map中最靠前,计数不为0的数字作为开始。
  4. 那么这个数字后面连续k个数字必须都有。
  5. 对后续数字的记录-1。
  6. 如果map里的记录没有,或者计数已经为0了,就可以return false了。
bool isPossibleDivide(vector<int>& nums, int k) 
{
	map<int, int> cnts;
	for (auto n : nums) cnts[n]++;

	for (auto it = cnts.begin(); it != cnts.end(); it++)
	{
		while (it->second != 0)
		{
			int _first = it->first;
			it->second--;
			for (int i = 1; i < k; i++)
			{
				int t = _first + i;
				if (cnts.count(t) == 0) return false;
				if (cnts[t]-- == 0) return false;
			}
		}
	}
	return true;
}

子串的最大出现次数

思路不混乱,但写法边界控制有问题,调整了好几次逻辑才对。

  1. 使用vector<int> chars(26, 0);记录字母使用情况。
  2. 配合上面,使用int curLetters = 0;记录不同字母的个数。
  3. 使用string curStr = "";记录minSize - 1长度的字符串。
  4. 遍历时,更新curStr,以及其字母使用情况。
  5. 然后复制出临时变量,对从minSize到maxSize的字符串判断。(后来发现并不需要考虑maxSize())
  6. 符合条件的加入到unordered_map<string, int> cnts;统计个数。
  7. 使用int ans = 0;记录最大值。
int maxFreq(string s, int maxLetters, int minSize, int maxSize) 
{
	int ans = 0;
	unordered_map<string, int> cnts;
	vector<int> chars(26, 0);
	int curLetters = 0;
	string curStr = "";

	for (size_t i = 0; i < s.size(); i++)
	{
		curStr += s[i];
		curLetters += (chars[s[i] - 'a']++ == 0);
		if (curStr.size() < minSize) continue;

		if (curLetters <= maxLetters)
		{
			cnts[curStr]++;
			ans = max(ans, cnts[curStr]);
		}

		curLetters -= (--chars[curStr[0] - 'a'] == 0);
		curStr.erase(curStr.begin());
	}

	return ans;
}

你能从盒子里获得的最大糖果数

  1. 按照题意模拟即可
  2. 使用vector<int> haveStatus(status.size(), 0);表示已经拿到手的盒子。
  3. 使用vector<int> keyStatus(status.size(), 0);表示已经取得的钥匙。
  4. 然后就从拿到手的盒子遍历,判断是否打开的,或者有钥匙。
    41. 如果能打开,执行打开操作。
    42. 拿糖果
    43. 拿盒子
    44. 拿钥匙
  5. 一直到没有盒子可以打开为止。
vector<int> getHaveBoxes(vector<int>& haveStatus)
{
	vector<int> ret;
	for (auto i = 0; i < haveStatus.size(); i++)
	{
		if (haveStatus[i] == 1)
		{
			ret.push_back(i);
		}
	}
	return ret;
}

int maxCandies(vector<int>& status, vector<int>& candies, vector<vector<int>>& keys, vector<vector<int>>& containedBoxes, vector<int>& initialBoxes) 
{
	vector<int> haveStatus(status.size(), 0);
	for (auto n : initialBoxes) haveStatus[n] = 1;
	vector<int> keyStatus(status.size(), 0);

	int ans = 0;

	bool flag = true;
	while (flag)
	{
		flag = false;

		auto have = getHaveBoxes(haveStatus);
		if (have.empty()) break;

		for (auto i : have)
		{
			if (status[i] == 1 || keyStatus[i] == 1)
			{
				flag = true;
				haveStatus[i] = 2;

				ans += candies[i];
				for (auto k : keys[i])
				{
					keyStatus[k] = 1;
				}
				for (auto c : containedBoxes[i])
				{
					haveStatus[c] = 1;
				}
			}
		}
	}
	return ans;
}

个人总结

被第三题折磨死了,错了好几次。
边界问题搞不清楚,还是经验太少。

第四题意外的简单,没先做第四题遗憾了。

又是一周只提交两道题,说好的保三争四,这几周表现都有点一言难尽。

再接再厉。
大家一起加油。

2

这次第四题难度略水撒~
不要问,问就是面向对象强行怼!

class Box:
    def __init__(self, ID, status, candies, keys, containedBoxes):
        self.ID = ID
        self.status = status
        self.candies = candies
        self.keys = keys
        self.containedBoxes = containedBoxes
        self.accessed = False


class Solution:

    boxList = list()
    accessedBox = set()
    accessedKey = set()
    total = 0

    def maxCandies(self, status, candies, keys, containedBoxes, initialBoxes) -> int:
        n = len(status)
        self.boxList = list()
        for i in range(n):
            curr = Box(i, status[i], candies[i], keys[i], containedBoxes[i])
            self.boxList.append(curr)

        self.accessedBox.clear()
        self.accessedKey.clear()
        self.total = 0

        for root in initialBoxes:
            rootBox = self.boxList[root]
            self.consTree(rootBox)

        for idx in self.accessedBox:
            idxBox = self.boxList[idx]
            if idxBox.ID in self.accessedKey or idxBox.status:
                self.total += idxBox.candies

        return self.total

    def consTree(self, box):
        self.accessedBox.add(box.ID)
        # self.accessedBox |= set(box.containedBoxes)
        self.accessedKey |= set(box.keys)
        if box.containedBoxes:
            for child in box.containedBoxes:
                childBox = self.boxList[child]
                self.consTree(childBox)
        return

1

对应四个题目的代码(第二题有惊喜)

第一题:统计位数为偶数的数字

int findNumbers(vector<int>& nums) {
        int result = 0;
        for(int i = 0; i < nums.size(); i++){
            int j = 0;
            while(nums[i]){
                j++;
                nums[i] /= 10;
            }
            if(j % 2 == 0){
                result++;
            }
        }
        return result;
    }

第二题,用一个map保存值对应的次数,然后根据连续的k个值+次数去判断。(c++中map如果不存在这个键值对,会自动创建一个且值为0)

bool isPossibleDivide(vector<int>& nums, int k) {
        if (nums.size() % k != 0)
            return false;
        if (k == 1)
            return true;
        
        map<int, int> count;
        
        for(auto& a : nums){
            count[a]++;
        }
        
        while(count.size() > 0){
            int start = count.begin()->first;
            int times = count.begin()->second;
            count.erase(start);
            for(int m = 1; m < k; m++){
                if(count[start + m] == 0 || count[start + m] < times){
                    return false;
                }
                count[start + m] -= times;
                if(count[start + m] <= 0){
                    count.erase(start + m);
                }
            }
        }
        return true;
    }

第三题:子串的最大出现次数

int maxFreq(string s, int maxLetters, int minSize, int maxSize) {
        map<string, int> count;
        for(int i = 0; i < s.size() - minSize + 1; i++){
            string ss = s.substr(i, minSize);
            map<char,int> t;
            for(auto& c : ss){
                t[c];
            }
            if(t.size() <= maxLetters){
                count[ss]++;
            }
        }
        if(count.size() <= 0){
            return 0;
        }
        int result = 0;
        for(auto& a : count){
            if(a.second > result){
                result = a.second;
            }
        }
        return result;
    }

第四题:你能从盒子里获得的最大糖果数

int maxCandies(vector<int>& status, vector<int>& candies, vector<vector<int>>& keys, vector<vector<int>>& containedBoxes, vector<int>& initialBoxes) {
        queue<int> boxs;
        vector<int> havaBoxs;
        map<int, int> ks;
        int result = 0;

        for(auto& i : initialBoxes){
            if(status[i]){
                boxs.push(i);
            }else{
                havaBoxs.push_back(i);
            }
        }

        while(!boxs.empty()){
            result += candies[boxs.front()];
            havaBoxs.insert(havaBoxs.begin(), containedBoxes[boxs.front()].begin(), containedBoxes[boxs.front()].end());
            for(int key : keys[boxs.front()]){
                ks[key] = 1;
            }
            for(int i = 0; i < havaBoxs.size();){
                if(ks[havaBoxs[i]] || status[havaBoxs[i]]){
                    boxs.push(havaBoxs[i]);
                    havaBoxs.erase(havaBoxs.begin() + i);
                }else{
                    i++;
                }
            }
            boxs.pop();
        }

        return result;
    }
1

第二题耗时一小时罚时5次,其它三题加起来耗时不到半小时罚时1次……