http://acm.hdu.edu.cn/showproblem.php?pid=5884
题意:
有个屌丝设计了一个程序,每次可以将k个数组进行合并,代价为这k个数组总的长度之和。现在另外一个屌丝要他最后合并成一个数组时的总代价不能超过T。求k的最小值。
思路:
贪心策略是长度越小的肯定先进行合并。一开始是直接用一个优先队列,但是这样会TLE的。。
后来改成了用两个队列进行模拟,先将数组排好序然后放入队列之中,每次合并之后的放入另一个队列之中,每次只需要再两个队列之中选择小的即可。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 #include<bitset> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,int> pll; 15 const int INF = 0x3f3f3f3f; 16 const int maxn=100000+5; 17 18 ll n,t; 19 int a[maxn]; 20 21 bool solve(int x) 22 { 23 queue<ll> q1,q2; 24 int left=(n-1)%(x-1); 25 if(left) for(int i=1;i<=x-1-left;i++) q1.push(0); 26 for(int i=1;i<=n;i++) q1.push(a[i]); 27 ll sum=0; 28 29 while(!q1.empty() || !q2.empty()) 30 { 31 int tmp=0; 32 for(int i=1;i<=x;i++) 33 { 34 if(q1.empty()) 35 { 36 tmp+=q2.front(); 37 q2.pop(); 38 } 39 else if(q2.empty()) 40 { 41 tmp+=q1.front(); 42 q1.pop(); 43 } 44 else 45 { 46 int u=q1.front(); 47 int v=q2.front(); 48 if(u<v) 49 { 50 tmp+=u; 51 q1.pop(); 52 } 53 else 54 { 55 tmp+=v; 56 q2.pop(); 57 } 58 } 59 } 60 sum+=tmp; 61 if(!q1.empty() || !q2.empty()) q2.push(tmp); 62 } 63 return sum<=t; 64 } 65 66 int main() 67 { 68 //freopen("in.txt","r",stdin); 69 int T; 70 scanf("%d",&T); 71 while(T--) 72 { 73 scanf("%lld%lld",&n,&t); 74 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 75 sort(a+1,a+n+1); 76 int ans=1; 77 int l=2,r=n; 78 while(l<=r) 79 { 80 int mid=(l+r)/2; 81 if(solve(mid)) {ans=mid;r=mid-1;} 82 else l=mid+1; 83 } 84 printf("%d\n",ans); 85 } 86 return 0; 87 }
时间: 2024-11-05 16:33:47