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

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 }
时间: 2024-10-01 04:53:25

【洛谷】P2073 送花 [2017年6月计划 线段树01]的相关文章

洛谷P2835 刻录光盘 [2017年6月计划 强连通分量02]

P2835 刻录光盘 题目描述 在JSOI2005夏令营快要结束的时候,很多营员提出来要把整个夏令营期间的资料刻录成一张光盘给大家,以便大家回去后继续学习.组委会觉得这个主意不错!可是组委会一时没有足够的空光盘,没法保证每个人都能拿到刻录上资料的光盘,又来不及去买了,怎么办呢?! 组委会把这个难题交给了LHC,LHC分析了一下所有营员的地域关系,发现有些营员是一个城市的,其实他们只需要一张就可以了,因为一个人拿到光盘后,其他人可以带着U盘之类的东西去拷贝啊! 可是,LHC调查后发现,由于种种原因

洛谷P1062 数列 [2017年6月计划 数论03]

P1062 数列 题目描述 给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列,例如,当k=3时,这个序列是: 1,3,4,9,10,12,13,… (该序列实际上就是:3^0,3^1,3^0+3^1,3^2,3^0+3^2,3^1+3^2,3^0+3^1+3^2,…) 请你求出这个序列的第N项的值(用10进制数表示). 例如,对于k=3,N=100,正确答案应该是981. 输入输出格式 输入格式: 输入文件只有1行,为2个正整数,用一个空格隔开

洛谷P1774 最接近神的人_NOI导刊2010提高(02) [2017年6月计划 线段树03]

P1774 最接近神的人_NOI导刊2010提高(02) 题目描述 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某种活动的图案.而石门上方用古代文写着“神的殿堂”.小FF猜想里面应该就有王室的遗产了.但现在的问题是如何打开这扇门…… 仔细研究后,他发现门上的图案大概是说:古代人认为只有智者才是最容易接近神明的.而最聪明的人往往通过一种仪式选拔出来.仪式大概是指,即将隐退的智者为他的候选人写下一串无序的数字,并让他们进行一种操作,即

洛谷P2826 [USACO08NOV]光开关Light Switching [2017年6月计划 线段树02]

P2826 [USACO08NOV]光开关Light Switching 题目描述 Farmer John tries to keep the cows sharp by letting them play with intellectual toys. One of the larger toys is the lights in the barn. Each of the N (2 <= N <= 100,000) cow stalls conveniently numbered 1..N

洛谷P1978 集合 [2017年6月计划 数论08]

P1978 集合 题目描述 集合是数学中的一个概念,用通俗的话来讲就是:一大堆数在一起就构成了集合.集合有如 下的特性: •无序性:任一个集合中,每个元素的地位都是相同的,元素之间是无序的. •互异性:一个集合中,任何两个元素都认为是不相同的,即每个元素只能出现一次. •确定性:给定一个集合,任给一个元素,该元素或者属于或者不属于该集合,二者必居 其一,不允许有模棱两可的情况出现. 例如 A = {1, 2, 3} 就是一个集合.我们可以知道, 1 属于 A ,即 1 ∈ A : 4 不属于 A

洛谷 P2073 送花

错误记录:21,32,41行goto写成continue导致没有读入x就continue了导致无限等待输入导致TLE 1 #include<cstdio> 2 #include<queue> 3 #include<set> 4 using namespace std; 5 typedef pair<int,int> P; 6 priority_queue<P> q1; 7 priority_queue<P,vector<P>,g

洛谷 P3380 【模板】二逼平衡树(树套树)

洛谷 P3380 [模板]二逼平衡树(树套树) 线段树套treap: 就是线段树每个节点放一个treap.建树复杂度应该是$n log n$,操作1,3,4,5的复杂度是$(log n)^2$,操作2的复杂度是$(log n)^3$. 操作3:找到线段树的对应叶子节点后找到要删除的值,在回溯的时候更新线段树相关的每一个节点(在treap中去掉要删除的值,再加入要加入的值) 操作1:将操作转化为统计(这个区间[l,r]内小于x的数的个数)+1.那么通过线段树将区间分解,然后对分解出的每一个区间对应

【模板】LIS模板 洛谷P1091 [NOIP2004提高组]合唱队形 [2017年4月计划 动态规划11]

以题写模板. 写了两个:n^2版本与nlogn版本 P1091 合唱队形 题目描述 N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足T1<...<Ti>Ti+1>…>TK(1<=i<=K). 你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形. 输入输出格

洛谷P3380 【模板】二逼平衡树(树套树,树状数组,线段树)

洛谷题目传送门 emm...题目名写了个平衡树,但是这道题的理论复杂度最优解应该还是树状数组套值域线段树吧. 就像dynamic ranking那样(蒟蒻的Sol,放一个link骗访问量233) 所有的值(包括初始a数组,操作1.3.4.5的k)全部先丢进去离散化 对于1操作查比它小的数,挑log棵线段树,找区间小于这个数的个数+1,这个还比较好像 操作2就是dynamic ranking,log棵线段树一起加减,像静态主席树求第k小一样跳,操作3 dynamic ranking里也有 操作4先