Codeforces 1070C Cloud Computing 二分 + 树状数组 + 扫描线

版权声明:本文为博主原创文章,未经博主允许不得转载。 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;
}

猜你喜欢

转载自blog.csdn.net/Tawn0000/article/details/83217954