【非原创】codeforces 1070C Cloud Computing 【线段树&树状数组】
题目:戳这里
学习博客:戳这里
题意:有很多个活动,每个活动有持续天数,每个活动会在每天提供C个CPU每个CPU价格为P,问需要工作N天,每天需要K个CPU的最少花费。
解题思路:遍历每一天,维护当前天K个cpu的最小花费。具体方法是维护两个线段树(树状数组也可以),维护每一天可以使用的cpu数和价格*cpu数的前缀和。注意数组下标是价格(1e6的数组。
(不明白的话可以看代码,代码思路很清晰
附学习博客的代码:
1 #include <iostream> 2 3 #include <algorithm> 4 5 #include <string.h> 6 7 #include <vector> 8 9 #include <memory.h> 10 11 #include <bitset> 12 13 #include <map> 14 15 #include <deque> 16 17 #include <math.h> 18 19 #include <stdio.h> 20 21 using namespace std; 22 23 typedef long long int ll; 24 25 const int MAXN = 1000005; 26 27 28 29 ll num[MAXN<<2]; 30 31 ll sum[MAXN<<2]; 32 33 int N; 34 35 void pushup(int rt){ 36 37 num[rt]=num[rt<<1]+num[rt<<1|1]; 38 39 sum[rt]=sum[rt<<1]+sum[rt<<1|1]; 40 41 } 42 43 44 45 void update(int P,int C,int l,int r,int rt){ 46 47 if(l==r){ 48 49 num[rt]+=C; 50 51 sum[rt]+=1ll*P*C; 52 53 return; 54 55 } 56 57 58 59 int m=(l+r)/2; 60 61 62 63 if(P<=m) 64 65 update(P,C,l,m,rt<<1); 66 67 else 68 69 update(P,C,m+1,r,rt<<1|1); 70 71 pushup(rt); 72 73 } 74 75 76 77 ll query(int K,int l,int r,int rt){ 78 79 80 81 if(l==r){ 82 83 //不到K个 84 85 if(l==MAXN){ 86 87 return 0; 88 89 } 90 91 if(K>0) 92 93 { 94 95 return 1ll*K*l; 96 97 } 98 99 else 100 101 return 0; 102 103 } 104 105 int m=(l+r)/2; 106 107 if(num[rt<<1]>=K){ 108 109 return query(K,l,m,rt<<1); 110 111 } 112 113 else{ 114 115 return sum[rt<<1]+query(K-num[rt<<1],m+1,r,rt<<1|1); 116 117 } 118 119 } 120 121 122 123 vector<pair<int,int> > C[MAXN];//第i天加入的活动 124 125 vector<pair<int,int> > O[MAXN];//第i天结束的活动 126 127 128 129 int main() 130 131 { 132 133 int K,M; 134 135 scanf("%d%d%d",&N,&K,&M); 136 137 138 139 int l,r,c,p; 140 141 for(int i=0;i<M;i++){ 142 143 scanf("%d%d%d%d",&l,&r,&c,&p); 144 145 C[l].push_back(make_pair(p,c));//加入的活动 146 147 O[r].push_back(make_pair(p,c));//退出的活动 148 149 } 150 151 152 153 ll ans=0; 154 155 for(int i=1;i<=N;i++){ 156 157 //新活动加入 158 159 for(int j=0;j<C[i].size();j++) 160 161 update(C[i][j].first,C[i][j].second,1,MAXN,1); 162 163 ans+=query(K,1,MAXN,1); 164 165 //活动结束 166 167 for(int j=0;j<O[i].size();j++) 168 169 update(O[i][j].first,-O[i][j].second,1,MAXN,1); 170 171 } 172 173 cout<<ans<<endl; 174 175 176 177 return 0; 178 179 }