洛谷 P3462 [POI2007]ODW-Weights

题面:

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 }
View Code

网上有高妙的一个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 }
View Code

 

posted @ 2018-10-31 11:41  hehe_54321  阅读(226)  评论(0编辑  收藏  举报
AmazingCounters.com