3 条题解

  • 1
    @ 2026-8-4 9:32:22

    只用两个 multisetmultiset 就够了,一个维护目前所有史莱姆的体力,一个维护 SS 集合中还有哪些数没出现过。

    #include<bits/stdc++.h>
    using namespace std;
    multiset<int>s,slm;
    int main()
    {
    	ios::sync_with_stdio(0);
    	cin.tie(0);cout.tie(0);
    	int n;cin>>n;int m=1<<n;
    	for(int i=1,x;i<=m;i++)cin>>x,s.insert(x);
    	int mx=*s.rbegin();
    	slm.insert(mx);s.erase(s.find(mx));
    	for(int t=1;t<=n;t++)for(int sz:slm)
    	{
    		auto it=s.lower_bound(sz);
    		if(it==s.begin()){cout<<"No\n";return 0;}
    		s.erase(--it);slm.insert(*it);
    	}
    	cout<<"Yes\n";return 0;
    }
    
    • 0
      @ 2026-7-5 22:07:37

      这个题可以直接根据题意模拟就行......

      贪心一下,可以发现一定是先生成大的再生成小的,并且大的数一定去生成刚好小于它的那个数。我们就可以根据这个贪心来模拟。

      然后模拟过程就需要一些乱搞了......比如我用了两个 multiset 和一个 set,一个 multiset 用来记录用来存还剩哪些数没生成,另一个用来存已经生成了哪些数,然后后面放数的时候就枚举第二个 multiset 来生成新的数。两个 multiset 都是默认从大到小排序的。

      然后我那个 set 就是用来存还有哪几种数没放,因为根据贪心,我们需要找到第一个刚好小于它的数来生成,就可以在 set 上面二分一下即可。然后如果这个数在第一个 multiset 已经没了,那么我们就在这个 set 中把这个数删掉即可。

      时间复杂度大概为 O(nlog2n)\mathcal{O}(n\log^2n).

      渣代码轻喷QAQ

      #include <bits/stdc++.h>
      #define ll long long
      #define ls id << 1
      #define rs id << 1 | 1
      #define mem(array, value, size, type) memset(array, value, ((size) + 5) * sizeof(type))
      #define memarray(array, value) memset(array, value, sizeof(array))
      #define pb(x) push_back(x)
      #define st(x) (1LL << (x))
      #define pii pair<int, int>
      #define mp(a, b) make_pair((a), (b))
      #define Flush fflush(stdout)
      using namespace std;
      const int N = 1000050;
      const int inf = 0x3f3f3f3f;
      const ll mod = 998244353LL;
      clock_t TIME_START, TIME_END;
      void program_end()
      {
      #ifdef ONLINE
          printf("\nTime used: %.6lf(s)\n", ((double)TIME_END - TIME_START) / CLOCKS_PER_SEC);
          system("pause");
      #endif
      }
      int n;
      int s[N];
      multiset<int, greater<int>> S1, S2;
      set<int> vis;
      int id[N];
      int tot;
      
      inline int Query(int x)
      {
          auto it = vis.lower_bound(x);
          if (it != vis.begin())
          {
              it--;
              return *it;
          }
          return -1;
      }
      
      void solve()
      {
          cin >> n;
          for (int i = 1; i <= st(n); ++i)
              scanf("%d", &s[i]);
          for (int i = 1; i <= st(n); ++i)
              vis.insert(s[i]);
          for (int i = 1; i <= st(n); ++i)
              S1.insert(s[i]);
          sort(s + 1, s + st(n) + 1, greater<int>());
          S2.insert(s[1]);
          S1.erase(S1.find(s[1]));
          if (S1.count(s[1]) == 0)
              vis.erase(s[1]);
          int tim = 1;
          vector<int> tmp;
          while (tim <= n)
          {
              // puts("flag");
              tmp.clear();
              for (auto &i : S2)
              {
                  int x = Query(i);
                  if (S1.empty())
                      return puts("Yes"), void();
                  if (x == -1 || S1.find(x) == S1.end())
                      return puts("No"), void();
                  S1.erase(S1.find(x));
                  if (S1.find(x) == S1.end())
                      vis.erase(x);
                  if (S1.empty())
                      return puts("Yes"), void();
                  tmp.push_back(x);
              }
              for (auto &i : tmp)
                  S2.insert(i);
              tim++;
          }
          puts("No");
      }
      
      int main()
      {
          TIME_START = clock();
          int Test = 1;
          // cin >> Test;
          while (Test--)
              solve();
          TIME_END = clock();
          program_end();
          return 0;
      }
      /*
      3
      5 4 4 4 3 3 2 1
      */
      
      • 0
        @ 2026-7-5 21:12:56

        ABC140F 题解

        我们可以知道,如果这种集合可以作为最后的结果,那么第一个史莱姆一定是最大的,然后我们考虑剩下的情况。

        对于每一秒,一个史莱姆一定生成的是剩余史莱姆中第一个小于它的史莱姆,这是一种贪心策略,一种可行的生成方式必然与上面这种相同。

        当一个物品无法生成比他小的史莱姆的时候,这种情况就会被判定为无解。

        我们使用三个 std::multiset 模拟即可。

        #include<iostream>
        #include<algorithm>
        #include<set>
        const int sz=3e5+10;
        int arr[sz];
        int main(){
            std::ios::sync_with_stdio(false);
            std::cin.tie(nullptr);
            int n,m;
            std::cin>>n,m=1<<n;
            for(int i=1;i<=m;i++)std::cin>>arr[i];
            std::sort(arr+1,arr+m+1,std::greater<int>());
            std::multiset<int,std::greater<int>>s,t;
            std::multiset<int>rest;
            s.insert(arr[1]),t.insert(arr[1]);
            for(int i=2;i<=m;i++)rest.insert(arr[i]);
            for(int i=1;i<=n;i++){
                for(int x:s){
                    auto it=rest.lower_bound(x);
                    if(it==rest.begin())std::cout<<"No\n",exit(0);
                    t.insert(*--it),rest.erase(it);
                }
                s=t;
            }
            std::cout<<"Yes\n";
            return 0;
        }
        
        • 1

        【STL:multiset + set】[ABC140F] Many Slimes

        信息

        ID
        11741
        时间
        2000ms
        内存
        1024MiB
        难度
        9
        标签
        递交数
        11
        已通过
        5
        上传者