【*2000】【2018-2019 ICPC, NEERC, Southern Subregional Contest C 】Cloud Computing
阿新 • • 發佈:2018-11-09
【連結】 我是連結,點我呀:)
【題意】
【題解】
我們可以很容易知道區間的每個位置有哪些安排可以用。
顯然
我們優先用那些花費的錢比較少的租用cpu方案。
但一個方案可供租用的cpu有限。
我們可以用一個線段樹
線段樹的下標表示價格。
那一位的值,為這個價格的cpu能租多少個。
弄個區間和(即這個價格的區間總共能租多少個(最多)
再弄另外一個區間和sum表示價格區間內的所有cpu都租,要花多少錢。
因為每個位置最多要租k個cpu
利用上面的兩個區間和則我們可以線上段樹上做一個二分。
找到租前k個最便宜的cpu要多少錢。(類似平衡樹的前k小的和)
(優先價格低的,所以先把左子樹選完,如果還不夠,再到右子樹裡面選(左子樹直接累加它的價格和就好) )
(如果最後發現l==r,說明當前這個價格l至少有k個,因為你不能多選,所以你恰好選k個就ok
注意線段樹的右端點是1e6,而不是n.
【程式碼】
#include <bits/stdc++.h> #define ll long long #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define rep1(i,a,b) for (int i = a;i <= b;i++) #define rep2(i,a,b) for (int i = a;i >= b;i--) using namespace std; const int N = 1e6; ll sc[N*4+10],sum[N*4+10]; vector<pair<int,int> > in[N+10],out[N+10]; int n,k,m,curi; void _updata(int l,int r,int rt,int price,int num){ if (l==r){ sc[rt]+=num; sum[rt]+=1LL*price*num; return; } int mid = (l+r)>>1; if (price<=mid) _updata(lson,price,num); else _updata(rson,price,num); sc[rt]=sc[rt<<1]+sc[rt<<1|1]; sum[rt] = sum[rt<<1]+sum[rt<<1|1]; } ll _query(int l,int r,int rt,int k){ if (k==0) return 0; if (sc[rt]<=k) return sum[rt]; if (l==r){ return 1LL*k*l; } //sc[rt]>k int mid = (l+r)>>1; ll temp = 0; if (sc[rt<<1]<=k) temp+=sum[rt<<1];else return _query(lson,k); return temp + _query(rson,k-sc[rt<<1]); } int main(){ #ifdef ccy freopen("rush.txt","r",stdin); #endif scanf("%d%d%d",&n,&k,&m); rep1(i,1,m){ int x,y,num,p; scanf("%d%d%d%d",&x,&y,&num,&p); in[x].push_back(make_pair(num,p)); out[y+1].push_back(make_pair(num,p)); } ll ans = 0; rep1(i,1,n){ curi = i; rep1(j,0,(int) in[i].size()-1){ int num = in[i][j].first,price = in[i][j].second; _updata(1,N,1,price,num); } rep1(j,0,(int) out[i].size()-1){ int num = out[i][j].first,price = out[i][j].second; _updata(1,N,1,price,-num); } ll temp1 = _query(1,N,1,k); ans += temp1; } printf("%lld\n",ans); return 0; }