3 条题解
-
1
只用两个 就够了,一个维护目前所有史莱姆的体力,一个维护 集合中还有哪些数没出现过。
#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
这个题可以直接根据题意模拟就行......
贪心一下,可以发现一定是先生成大的再生成小的,并且大的数一定去生成刚好小于它的那个数。我们就可以根据这个贪心来模拟。
然后模拟过程就需要一些乱搞了......比如我用了两个 multiset 和一个 set,一个 multiset 用来记录用来存还剩哪些数没生成,另一个用来存已经生成了哪些数,然后后面放数的时候就枚举第二个 multiset 来生成新的数。两个 multiset 都是默认从大到小排序的。
然后我那个 set 就是用来存还有哪几种数没放,因为根据贪心,我们需要找到第一个刚好小于它的数来生成,就可以在 set 上面二分一下即可。然后如果这个数在第一个 multiset 已经没了,那么我们就在这个 set 中把这个数删掉即可。
时间复杂度大概为 .
渣代码轻喷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
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
信息
- ID
- 11741
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 9
- 标签
- 递交数
- 11
- 已通过
- 5
- 上传者