Codeforces 1070C Cloud Computing 二分 + 樹狀陣列 + 掃描線
阿新 • • 發佈:2018-12-24
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; }