【题目描述:】
这些花都很漂亮,每朵花有一个美丽值W,价格为C。
小明一开始有一个空的花束,他不断地向里面添加花。他有以下几种操作:
操作 含义
1 W C 添加一朵美丽值为W,价格为C的花。
3 小明觉得当前花束中最便宜的一朵花太廉价,不适合送给小红,所以删除最便宜的一朵花。
2 小明觉得当前花束中最贵的一朵花太贵,他心疼自己的钱,所以删除最贵的一朵花。
-1 完成添加与删除,开始包装花束
若删除操作时没有花,则跳过删除操作。
如果加入的花朵价格已经与花束中已有花朵价格重复,则这一朵花不能加入花束。
请你帮小明写一个程序,计算出开始包装花束时,花束中所有花的美丽值的总和,以及小明需要为花束付出的总价格。
【输入格式:】
若干行,每行一个操作,以-1结束。
【输出格式:】
一行,两个空格隔开的正整数表示开始包装花束时,花束中所有花的美丽值的总和。以及小明需要为花束付出的总价格。
/* 输入样例#1: 1 1 1 1 2 5 2 1 3 3 3 1 5 2 -1 输出样例#1: 8 5 */
【算法分析:】
方法一:红黑树.
手写红黑树是不可能的,但是可以用stl里的map水(set好像也可以不过应该比map慢一些)
map里的key-value其实就是pair,而且map里的元素是有序的:
默认按key从小到大排,所以求c的最值时应把make_pair(c, w)加入map
所以删除最小的元素就是删除map中的第一个元素,删除最大的元素就是删除map中的最后一个。
删除操作可以通过erase(iterator)来实现,定义一个map<int, int> a,
则第一个元素的位置为a.begin()
最后一个元素的位置就是 --a.end()
最后累加的时候通过迭代器遍历map,用a->first和a->second访问key, value的值
去重的话加一个bool数组去重就好
1 //P2073 送花 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #include<map> 6 #define mkp make_pair 7 #define fi first 8 #define se second 9 using namespace std; 10 11 const int MAXN = 1000000 + 1; 12 13 map<int, int> a; 14 bool vis[MAXN]; 15 16 int main() { 17 int fl, w, c; 18 while(scanf("%d", &fl) == 1 && fl != -1) { 19 if(fl == 1) { 20 scanf("%d%d", &w, &c); 21 if(vis[c]) continue; 22 a.insert(mkp(c, w)); 23 vis[c] = 1; 24 } 25 if(fl == 2) { 26 if(!a.size()) continue; 27 map<int, int>::iterator it; 28 it = a.end(); 29 --it; vis[it->fi] = 0; 30 a.erase(it); 31 } 32 if(fl == 3) { 33 if(!a.size()) continue; 34 map<int, int>::iterator it; 35 it = a.begin(); 36 vis[it->fi] = 0; 37 a.erase(it); 38 } 39 } 40 long long sum1 = 0, sum2 = 0; 41 map<int, int>::iterator it; 42 for(it=a.begin(); it!=a.end();++it) 43 sum1 += it->se, sum2 += it->fi; 44 printf("%lld %lld\n", sum1, sum2); 45 }
方法二:堆
要求最大值和最小值并删除,很容易想到通过堆来实现
开一个小根堆p1和一个大根堆p2,
vis[c]表示价格为c的花的美丽度,vis[c]=0表示没有这朵花
每次读入把c分别push进两个堆里,记录vis[c]
两个变量sum1, sum2分别累加c和w,
在删除的时候sum1, sum2要分别减去c和vis[c]
1 //P2073 送花 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 8 const int MAXN = 1000000 + 1; 9 10 int vis[MAXN]; 11 priority_queue<int, vector<int>, greater<int> > q1; 12 priority_queue<int> q2; 13 14 int main() { 15 int fl, w, c; 16 long long sum1 = 0, sum2 = 0; 17 while(scanf("%d", &fl) == 1 && fl != -1) { 18 if(fl == 1) { 19 scanf("%d%d", &w, &c); 20 if(vis[c]) continue; 21 q1.push(c), q2.push(c); 22 vis[c] = w; 23 sum1 += w, sum2 += c; 24 } 25 if(fl == 2) { 26 while(!q2.empty() && !vis[q2.top()]) q2.pop(); 27 if(q2.empty()) continue; 28 int t = q2.top(); 29 sum1 -= vis[t]; 30 sum2 -= t; 31 vis[t] = 0; 32 q2.pop(); 33 } 34 if(fl == 3) { 35 while(!q1.empty() && !vis[q1.top()]) q1.pop(); 36 if(q1.empty()) continue; 37 int t = q1.top(); 38 sum1 -= vis[t]; 39 sum2 -= t; 40 vis[t] = 0; 41 q1.pop(); 42 } 43 } 44 printf("%lld %lld\n", sum1, sum2); 45 }