题面:
https://www.luogu.org/problemnew/show/P3462
https://www.lydsy.com/JudgeOnline/problem.php?id=1110
https://szkopul.edu.pl/problemset/problem/y7tXjqVq0gPZjc8kPrscs2CJ/site/?key=statement
先打了个贪心。直接所有容器从大到小排序,按这个顺序处理容器,每个容器每次装能够装进且最大的砝码。用multiset维护。
WA了(貌似洛谷还骗到40分?)
然后想了想改了一下。先二分答案,对于每个二分出的答案x显然最好方案是取最小的x个砝码。然后就当做只有这些砝码,用前面的贪心判是否能够取完这些砝码。
错误记录:没有对砝码按重量排序...
A掉了?(n*log^2而且常数大,因此bzojA不掉,其他两个地方可以A)而且貌似容器不排序(甚至random_shuffle)都没有关系?
不太会证..
1 #pragma GCC optimize("Ofast") 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<vector> 6 #include<set> 7 using namespace std; 8 #define fi first 9 #define se second 10 #define mp make_pair 11 #define pb push_back 12 typedef long long ll; 13 typedef unsigned long long ull; 14 typedef pair<int,int> pii; 15 int n,m; 16 int a[200010],b[200010]; 17 multiset<int> s; 18 bool judge(int x) 19 { 20 s.clear(); 21 int i,t;multiset<int>::iterator i1; 22 for(i=1;i<=x;++i) 23 s.insert(b[i]); 24 for(i=n;i>=1;--i) 25 { 26 t=a[i]; 27 while(!s.empty()&&((i1=s.upper_bound(t))!=s.begin())) 28 { 29 --i1; 30 t-=*i1; 31 s.erase(i1); 32 } 33 } 34 return s.empty(); 35 } 36 int main() 37 { 38 int i; 39 scanf("%d%d",&n,&m); 40 for(i=1;i<=n;++i) 41 scanf("%d",&a[i]); 42 sort(a+1,a+n+1); 43 for(i=1;i<=m;++i) 44 scanf("%d",&b[i]); 45 sort(b+1,b+m+1); 46 int l=0,r=m,mid; 47 while(l!=r) 48 { 49 mid=l+((r-l)>>1); 50 if(judge(mid+1)) l=mid+1; 51 else r=mid; 52 } 53 printf("%d",l); 54 return 0; 55 }
网上有高妙的一个log做法
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 #define fi first 7 #define se second 8 #define mp make_pair 9 #define pb push_back 10 typedef long long ll; 11 typedef unsigned long long ull; 12 typedef pair<int,int> pii; 13 int n,m; 14 int a[200010],b[200010],c[200010]; 15 int d[200]; 16 int ans; 17 void try_work(int p) 18 { 19 if(p>c[0]) return; 20 if(d[p]>=1) 21 { 22 --d[p]; 23 d[p-1]+=c[p]/c[p-1]; 24 } 25 else 26 { 27 try_work(p+1); 28 if(d[p]>=1) 29 { 30 --d[p]; 31 d[p-1]+=c[p]/c[p-1]; 32 } 33 } 34 } 35 int main() 36 { 37 int i,j; 38 scanf("%d%d",&n,&m); 39 for(i=1;i<=n;++i) 40 scanf("%d",&a[i]); 41 for(i=1;i<=m;++i) 42 scanf("%d",&b[i]); 43 sort(b+1,b+m+1); 44 for(i=1;i<=m;++i) 45 c[++c[0]]=b[i]; 46 c[0]=unique(c+1,c+c[0]+1)-c-1; 47 for(i=1;i<=n;++i) 48 for(j=c[0];j>=1;--j) 49 { 50 d[j]+=a[i]/c[j]; 51 a[i]%=c[j]; 52 } 53 for(i=1,j=1;i<=m;++i) 54 { 55 while(c[j]<b[i]) ++j; 56 if(d[j]>=1) 57 { 58 --d[j]; 59 ++ans; 60 } 61 else 62 { 63 try_work(j+1); 64 if(d[j]>=1) 65 { 66 --d[j]; 67 ++ans; 68 } 69 } 70 } 71 printf("%d",ans); 72 return 0; 73 }