版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Tawn0000/article/details/83217954
Codeforces 1070C Cloud Computing
将左右端点分配到1-n上的各个点,然后从1-n 进行扫描线处理,维护两个数状数组,c[i],b[i], c[i]维护当前时间下,可用方案按时间排序的数量,b[i] 维护 i*c[i] 即价格和, 然后二分适合的价格,满足 数量 >= k, 如果 > k 回退一部分,注意longlong,wrong 样例 32,33 都是爆int的原因!
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
typedef long long LL;
LL b[maxn];
LL c[maxn];
LL cc[maxn];
LL p[maxn];
LL n,k,m,li,ri,ci,pi;
vector <int> l[maxn];
vector <int> r[maxn];
int N = 1e6+2;
bool check(int mid)
{
LL res = 0;
for(int x = mid; x; x -= x&-x) res += c[x];
if(res >= k) return true;
else return false;
}
int main()
{
scanf("%lld%lld%lld",&n,&k,&m);
for(int i = 1; i <= m; i++)
{
scanf("%lld%lld%lld%lld",&li,&ri,&cc[i],&p[i]);
l[li].push_back(i);
r[ri].push_back(i);
}
memset(c,0,sizeof(c));
memset(b,0,sizeof(b));
LL ans = 0;
for(int i = 1; i <= n; i++)
{
for(int j = 0; j < l[i].size(); j++)
{
int t = l[i][j];
// cout <<t <<endl;
for(int x = p[t]; x < N; x += x&-x) c[x] += cc[t];
for(int x = p[t]; x < N; x += x&-x) b[x] += p[t]*cc[t];
}
int st = 0, ed = 1e6+1;
while(ed - st > 1)
{
int mid = st + (ed-st)/2;
if(check(mid)) ed = mid;
else st = mid;
}
LL num = 0,res = 0;
for(int x = ed; x ; x-= x&-x) num += c[x],res += b[x];
LL num1 = 0;
for(int x = st; x; x -= x&-x) num1 += c[x];
if(num1 == num) ed = st;
ans += res - max(0LL,(num-k))*ed;
//cout <<ed << " " << res << " " << num << endl;
for(int j = 0; j < r[i].size(); j++)
{
int t = r[i][j];
for(int x = p[t]; x < N; x += x&-x) c[x] -= cc[t];
for(int x = p[t]; x < N; x += x&-x) b[x] -= p[t]*cc[t];
}
}
printf("%lld\n",ans);
return 0;
}