2019年ccpc女生赛重现赛题解C

2019年ccpc女生赛重现赛题解C

题目:
Function
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 0 Accepted Submission(s): 0

Problem Description
wls 有 n 个二次函数 Fi(x) = aix2 + bix + ci (1 ≤ i ≤ n).
现在他想在∑ni=1xi = m 且 x 为正整数的条件下求∑ni=1Fi(xi)的最小值。
请求出这个最小值。

Input
第一行两个正整数 n, m。
下面 n 行,每行三个整数 a, b, c 分别代表二次函数的二次项, 一次项,常数项系数。
1 ≤ n ≤ m ≤ 100, 000
1 ≤ a ≤ 1, 000
−1, 000 ≤ b, c ≤ 1, 000

Output
一行一个整数表示答案。

Sample Input

2 3
1 1 1
2 2 2

Sample Output

13


思路,m先是必须先给每个函数式分至少一个1,求出和,然后对于m剩下的数字,求出每一个加上1能增加的数字利用优先队列维护给加上1后增加最少的函数加上1,最后得出结果,学长a的这题orz,tql。

AC代码:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define fi first
#define se second
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define root 1,n,1
#define PB push_back
#define MP make_pair
#define pi 3.1415926535898
#define MS(x,y) memset(x,y,sizeof(x))
#define lowbit(a)  (a&(-a))

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<LL,LL> P;
const int maxn = 1e5 + 10,modd = 1e9 + 7,inf = 0x3f3f3f3f,INF = 0x7fffffff,hmod1=0x48E2DCE7,hmod2=0x60000005;
const int dir[4][2] = {{-1,0},{0,-1},{1,0},{0,1}};
const double eps = 1e-8;

template <class T> inline void scand(T &x){char c;x=0;while((c=getchar())<'0');while(c>='0'&&c<='9')x=x*10+(c-48),c=getchar();}
inline LL min(LL a,LL b){return a < b ? a : b;}
inline LL max(LL a,LL b){return a > b ? a : b;}
inline LL gcd(LL a,LL b){ return b==0? a: gcd(b,a%b); }
inline LL exgcd(LL a,LL b,LL &x,LL &y){ LL d; (b==0? (x=1,y=0,d=a): (d=exgcd(b,a%b,y,x),y-=a/b*x)); return d; }
inline LL qpow(LL a,LL n){LL sum=1;while(n){if(n&1)sum=sum*a%modd;a=a*a%modd;n>>=1;}return sum;}
inline LL qmul(LL a,LL n){LL sum=0;while(n){if(n&1)sum=(sum+a)%modd;a=(a+a)%modd;n>>=1;}return sum;}
inline LL inv(LL a) {return qpow(a,modd-2);}
inline LL madd(LL a,LL b){return (a%modd+b%modd)%modd;}
inline LL mmul(LL a,LL b){return a%modd * b%modd;}
inline void uadd(LL &a,LL b){a = madd(a,b);}
inline void umul(LL &a,LL b){a = mmul(a,b);}

struct Node
{
  LL id,x,val;
  bool operator < (const Node &a) const{
    return val > a.val;
  }
};

LL n,m,summ,sumc,a[maxn],b[maxn],c[maxn];
priority_queue<Node> pq;


int main()
{
  ios::sync_with_stdio(false);
  cin.tie(0);cout.tie(0);
  cin >> n >> m;
  for(int i=1;i<=n;i++)
  {
    cin >> a[i] >> b[i] >> c[i];
    summ += (a[i] + b[i] + c[i]);
    pq.push(Node{i,2,3*a[i]+b[i]});
  }
  for(int i=0;i<m-n;i++)
  {
    Node f = pq.top();pq.pop();
    summ += f.val;
    pq.push(Node{f.id,f.x+1,a[f.id]*(f.x+1)*(f.x+1)+b[f.id]*(f.x+1)-a[f.id]*(f.x)*(f.x)-b[f.id]*f.x});
  }
  cout << summ << endl;
}

你可能感兴趣的:(优先队列及其优化运用)