首页 > 代码库 > 【洛谷】P2073 送花 [2017年6月计划 线段树01]

【洛谷】P2073 送花 [2017年6月计划 线段树01]

P2073 送花

题目背景

小明准备给小红送一束花,以表达他对小红的爱意。他在花店看中了一些花,准备用它们包成花束。

题目描述

这些花都很漂亮,每朵花有一个美丽值W,价格为C。

小明一开始有一个空的花束,他不断地向里面添加花。他有以下几种操作:

操作 含义

1 W C 添加一朵美丽值为W,价格为C的花。

3 小明觉得当前花束中最便宜的一朵花太廉价,不适合送给小红,所以删除最便宜的一朵花。

2 小明觉得当前花束中最贵的一朵花太贵,他心疼自己的钱,所以删除最贵的一朵花。

-1 完成添加与删除,开始包装花束

若删除操作时没有花,则跳过删除操作。

如果加入的花朵价格已经与花束中已有花朵价格重复,则这一朵花不能加入花束。

请你帮小明写一个程序,计算出开始包装花束时,花束中所有花的美丽值的总和,以及小明需要为花束付出的总价格。

输入输出格式

输入格式:

若干行,每行一个操作,以-1结束。

输出格式:

一行,两个空格隔开的正整数表示开始包装花束时,花束中所有花的美丽值的总和。以及小明需要为花束付出的总价格。

输入输出样例

输入样例#1:
1 1 11 2 521 3 331 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 }

 

 

【洛谷】P2073 送花 [2017年6月计划 线段树01]