码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2017-06-07 23:13:59      阅读:251      评论:0      收藏:0      [点我收藏+]

标签:表达   美丽   play   turn   amp   整数   splay   读取   说明   

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 }

 

 

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

标签:表达   美丽   play   turn   amp   整数   splay   读取   说明   

原文地址:http://www.cnblogs.com/huibixiaoxing/p/6959437.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!