函数 - 贪心

题面

题解

其实就是一个贪心,可以用优先队列之类的实时存下一步的最小方案。

但我由于没有仔细读题而爆零了。

#include<cstdio> 
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<set>
#define LL long long
using namespace std;
inline LL read() {
	LL f = 1,x = 0;char s = getchar();
	while(s < '0' || s > '9') {if(s == '-')f = -1;s = getchar();}
	while(s >= '0' && s <= '9'){x = x * 10 + s - '0';s = getchar();}
	return x * f;
}
struct it{
	LL i,x;
	it(){i = x = 0;}
	it(LL I,LL X){i = I;x = X;}
}d[100005];
LL n,m,i,j,s,o,k;
LL a[100005],b[100005],c[100005];
LL I,J; 
bool flag;
LL js(LL i,LL x) {
	return a[i] *1ll *x *1ll *x + b[i] *1ll* x + c[i]*1ll;
}
LL check(LL j) {
	return js(I,j);
}
LL delta(LL i,LL x) {
	LL no = js(i,x);
	LL l = js(i,x - 1ll) - no;
	LL r = js(i,x + 1ll) - no;
	if(x - 1ll < 1ll) l = 1e18;
	return (flag ? l:r);
}
bool operator < (it a,it b) {
	return delta(a.i,a.x) > delta(b.i,b.x);
}
priority_queue<it> p;
LL solve(LL l,LL r) {
	if(l >= r - 2ll) {
		LL ans = r;
		LL minn = check(r);
		LL min2;
		if((min2 = check(l)) < minn) ans = l,minn = min2;
		if(check((l + r) / 2ll) < minn) ans = (l + r) / 2ll;
		return ans;
	}
	LL mid1 = (l + l + r) / 3ll,mid2 = (l + r + r) / 3ll;
	if(check(mid1) < check(mid2)) return solve(l,mid2);
	return solve(mid1,r);
}
int main() {
	freopen("function.in","r",stdin);
	freopen("function.out","w",stdout);
	n = read();m = read();
	LL ans = 0;
	for(int i = 1;i <= n;i ++) {
		a[i] = read();b[i] = read();c[i] = read();
		I = i;
		LL x = solve(1,200000);
		x = max(1ll,x);
		m -= x;
//		printf("%d: %d\n",i,x);
		ans += js(i,x);
		d[i] = it(i,x);
//		cout<<ans<<endl;
	}
	if(m > 0) {
		flag = 0;
		for(int i = 1;i <= n;i ++) p.push(d[i]);
		while(m > 0) {
			it t = p.top();
			p.pop();
			ans += delta(t.i,t.x);
//			printf("%lld %lld\n",ans,delta(t.i,t.x));
			p.push(it(t.i,t.x + 1ll));
			m --;
		}
	}
	else if(m < 0) {
		flag = 1;
		for(int i = 1;i <= n;i ++) p.push(d[i]);
		while(m < 0) {
			it t = p.top();
			p.pop();
			ans += delta(t.i,t.x);
//			printf("%lld %lld\n",ans,delta(t.i,t.x));
			p.push(it(t.i,t.x - 1ll));
			m ++;
		}
	}
	printf("%lld\n",ans);
	return 0;
}

 

posted @ 2019-11-30 12:29  DD_XYX  阅读(59)  评论(0)    收藏  举报