Giving two integers and and two arrays and both with length , you should construct an array also with length which satisfied:
1.0≤Ci≤Ai(1≤i≤n)
2.
and make the value S be minimum. The value S is defined as:
Giving two integers and and two arrays and both with length , you should construct an array also with length which satisfied:
1.0≤Ci≤Ai(1≤i≤n)
2.
and make the value S be minimum. The value S is defined as:
There are multiple test cases. In each test case, the first line contains two integers n(1≤n≤1000) andm(1≤m≤100000). Then two lines followed, each line contains n integers separated by spaces, indicating the array Aand B in order. You can assume that 1≤Ai≤100 and 1≤Bi≤10000 for each i from 1 to n, and there must be at least one solution for array C. The input will end by EOF.
For each test case, output the minimum value S as the answer in one line.
3 4
2 3 4
1 1 1
6
In the sample, you can construct an array [1,1,2](of course [1,2,1] and [2,1,1] are also correct), and is 6.
首先因为c数组的每个元素可以选择的范围都不相同,且c数组的所有元素之和还得大于等于m,如果开始值随便选的话并不能保证满足条件
所以我们可以从最大值开始考虑,即令Ci=Ai,这时前两个条件是必定满足的,但此时得到的是最大的S,即Smax
那我们要做的是将Ci减小,当我们将Ci减小为Ci-1,那S减少了多少呢?
由上述可知,要想使S尽可能小,我们要做的就是使△S尽可能大
所以我们可以用一个优先队列,按照(2C-1)*B从大到小排列,每次将队首元素进行处理,直到c数组所有元素之和等于m时结束,这是我们得到的S即为Smin,当然在处理过程中,当某一项Ci=0之后就不能再放进队列了,因为Ci的取值最小为0
/*Sherlock and Watson and Adler*/ #pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<stdlib.h> #include<queue> #include<stack> #include<math.h> #include<vector> #include<map> #include<set> #include<cmath> #include<complex> #include<string> #include<algorithm> #include<iostream> #define exp 1e-10 using namespace std; const int N = 1005; const int M = 40; const int inf = 100000000; const int mod = 2009; struct node { int c,b; bool operator < (const node &a) const { return (2*c-1)*b<(2*a.c-1)*a.b;//最大值优先 } node(){} node(int c0,int b0):c(c0),b(b0){} }; int a[N],b[N]; priority_queue<node> q; int main() { int n,i; long long ans,m,k; node u; while(~scanf("%d%lld",&n,&m)) { while(!q.empty()) q.pop(); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(k=ans=0,i=1;i<=n;i++) { scanf("%d",&b[i]); ans+=a[i]*a[i]*b[i]; q.push(node(a[i],b[i])); k+=a[i]; } while(k>m) { u=q.top(); q.pop(); ans-=(2*u.c-1)*u.b; if(u.c-1>0) q.push(node(u.c-1,u.b)); k--; } printf("%lld\n",ans); } return 0; } /************************************************************** Problem: 18 Language: C++ Result: Accepted Time:34 ms Memory:1520 kb ****************************************************************/
菜鸟成长记