bzoj 4868: [Shoi2017]期末考试
4868: [Shoi2017]期末考试
题意:略
一开始xjb贪心了好长时间...
然后发现可以从后往前枚举最晚时间,\(O(1)\)得到最小代价
确定最晚时间后就可以知道哪些可以用A啦!
一定要考虑这种变化变成不变的思想!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 1e5+5;
inline int read() {
char c=getchar(); int x=0,f=1;
while(c<'0' || c>'9') {if(c=='-')f=-1; c=getchar();}
while(c>='0' && c<='9') {x=x*10+c-'0'; c=getchar();}
return x*f;
}
ll a, b, c, ans, now, big_cnt, big_sum, les_cnt, les_sum, s[N];
int n, m, r[N], w[N], p, cnt_b, t[N];
void solve() {
ll cnt = 0;
for(int i=1; i<=p; i++) cnt += t[i-1], s[i] = s[i-1] + cnt;
ans = c >= 1e12 ? c : s[p] * c;
for(int i=1; i<=p; i++) les_cnt += w[i-1], les_sum += les_cnt;
while(p >= 2) {
p--; // p+1 --> p
big_cnt += w[p+1]; big_sum += big_cnt;
les_sum -= les_cnt; les_cnt -= w[p];
if(c >= 1e12 && s[p]) continue;
now = s[p] * c;
//printf("hi %d %lld %lld %lld %lld %lld\n", p, s[p], big_cnt, big_sum, les_cnt, les_sum);
if(b <= a)
now += b * big_sum;
else {
ll k = big_sum - les_sum;
if(k > 0) now += k * b + les_sum * a;
else now += big_sum * a;
}
ans = min(ans, now);
}
printf("%lld", ans);
}
int main() {
freopen("in", "r", stdin);
scanf("%lld %lld %lld", &a, &b, &c);
n=read(); m=read();
for(int i=1; i<=n; i++) t[read()]++;
for(int i=1; i<=m; i++) r[i] = read(), w[r[i]]++, p = max(p, r[i]);
solve();
}
Copyright:http://www.cnblogs.com/candy99/