P2073 送花
题目背景
小明准备给小红送一束花,以表达他对小红的爱意。他在花店看中了一些花,准备用它们包成花束。
题目描述
这些花都很漂亮,每朵花有一个美丽值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
说明
对于20%数据,操作数<=100,1<=W,C<=1000。
对于全部数据,操作数<=100000,1<=W,C<=1000000。
此题可谓练习线段树、Set、Treap、Splay的好题。
线段树做法:离线读取所有添加数据和操作,删除的时候向下dfs结束后向上更新即可。需要维护四个值,耐心写!猥琐发育别浪!
细节:别把美丽和价钱反了
左移右移别手残(比如我)
别忘了long long
以上。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 inline int max(int a,int b) {return a > b ? a : b;} 7 inline int min(int a,int b) {return a > b ? b : a;} 8 const int MAXN = 100000 + 10; 9 inline void read(long long &x){ 10 x = 0;char ch = getchar();char c = ch; 11 while(ch > '9' || ch < '0')c = ch, ch = getchar(); 12 while(ch >= '0' && ch <= '9')x = x * 10 + ch - '0',ch = getchar(); 13 if(c == '-')x = -x; 14 } 15 long long work[MAXN],num[MAXN][2],tmp,n,m;bool b[1000000 + 10]; 16 struct STNODE{ 17 long long l,r,max,min,sum,ssum; 18 }stnode[(MAXN << 2 )+ 10]; 19 void build(int o = 1, int l = 1, int r = m){ 20 stnode[o].l = l;stnode[o].r = r; 21 if(l == r){ 22 stnode[o].max = l; 23 stnode[o].min = l; 24 stnode[o].sum = num[l][1]; 25 stnode[o].ssum = num[l][0]; 26 return; 27 } 28 int mid = (l + r) >> 1; 29 build(o << 1, l, mid); 30 build(o << 1 | 1, mid + 1, r); 31 if(num[stnode[o << 1].max][0] > num[stnode[o << 1 | 1].max][0])stnode[o].max = stnode[o << 1].max; 32 else stnode[o].max = stnode[o << 1 | 1].max; 33 if(num[stnode[o << 1].min][0] < num[stnode[o << 1 | 1].min][0]) stnode[o].min = stnode[o << 1].min; 34 else stnode[o].min = stnode[o << 1 | 1].min; 35 stnode[o].sum = stnode[o << 1].sum + stnode[o << 1 | 1].sum; 36 stnode[o].ssum = stnode[o << 1].ssum + stnode[o << 1 | 1].ssum; 37 } 38 void cutoff(int p, int o = 1){ 39 int l = stnode[o].l;int r = stnode[o].r; 40 if(l == r && l == p){ 41 stnode[o].ssum = stnode[o].sum = stnode[o].max = stnode[o].min = 0; 42 return; 43 } 44 int mid = (l + r) >> 1; 45 if(mid >= p) cutoff(p, o << 1); 46 else cutoff(p, o << 1 | 1); 47 stnode[o].sum = 0; 48 stnode[o].ssum = 0; 49 stnode[o].sum = stnode[o << 1].sum + stnode[o << 1 | 1].sum; 50 stnode[o].ssum = stnode[o << 1].ssum + stnode[o << 1 | 1].ssum; 51 if(num[stnode[o << 1].max][0] > num[stnode[o << 1 | 1].max][0]) stnode[o].max = stnode[o << 1].max; 52 else stnode[o].max = stnode[o << 1 | 1].max; 53 if(stnode[o << 1].min == 0 && stnode[o << 1 | 1].min == 0) stnode[o].min = 0; 54 else if(stnode[o << 1].min == 0) stnode[o].min = stnode[o << 1 | 1].min; 55 else if(stnode[o << 1 | 1].min == 0) stnode[o].min = stnode[o << 1].min; 56 else { 57 if(num[stnode[o << 1].min][0] < num[stnode[o << 1 | 1].min][0]) stnode[o].min = stnode[o << 1].min; 58 else stnode[o].min = stnode[o << 1 | 1].min; 59 } 60 } 61 int query_max(int ll,int rr,int o = 1){ 62 int ans1 = 0;int ans2 = 0; 63 int l = stnode[o].l;int r = stnode[o].r; 64 if(l >= ll && r <= rr) return stnode[o].max; 65 int mid = (l + r) >> 1; 66 if(mid >= ll) ans1 = query_max(ll, rr, o << 1); 67 if(mid < rr) ans2 = query_max(ll, rr, o << 1 | 1); 68 if(ans1 == 0 && ans2 == 0) return 0; 69 if(num[ans1][0] > num[ans2][0]) return ans1; 70 else return ans2; 71 } 72 int query_min(int ll,int rr,int o = 1){ 73 int ans1 = 0;int ans2 = 0; 74 int l = stnode[o].l;int r = stnode[o].r; 75 if(l >= ll && r <= rr) return stnode[o].min; 76 int mid = (l + r) >> 1; 77 if(mid >= ll) ans1 = query_min(ll, rr, o << 1); 78 if(mid < rr) ans2 = query_min(ll, rr, o << 1 | 1); 79 if(ans1 == 0 && ans2 == 0) return 0; 80 else if(ans1 == 0) return ans2; 81 else if(ans2 == 0) return ans1; 82 else { 83 if(num[ans1][0] < num[ans2][0]) return ans1; 84 else return ans2; 85 } 86 } 87 int main(){ 88 read(tmp); 89 while(tmp != -1){ 90 n ++; 91 if(tmp == 1){m ++;read(num[m][1]);read(num[m][0]);} 92 else if(tmp == 2) work[n] = 1; 93 else work[n] = 2; 94 read(tmp); 95 } 96 if(m >= 1) build(); 97 int j = 0;int len = 0; 98 for(int i = 1;i <= n;i ++){ 99 if(work[i] == 1 && len < j){ 100 int a = query_max(1, j); 101 cutoff(a); 102 b[num[a][0]] = false; 103 len ++; 104 } 105 else if(work[i] == 2 && len < j){ 106 int a = query_min(1, j); 107 cutoff(a); 108 b[num[a][0]] = false; 109 len ++; 110 } 111 else if(!work[i]){ 112 j ++; 113 if(!b[num[j][0]]) b[num[j][0]] = true; 114 else cutoff(j); 115 } 116 } 117 printf("%lld %lld", stnode[1].sum, stnode[1].ssum); 118 return 0; 119 }