洛谷P2073 送花_Treap

来源:互联网 发布:免费钢材销售软件 编辑:程序博客网 时间:2024/06/14 06:30

题目背景

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

题目描述

这些花都很漂亮,每朵花有一个美丽值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。

经典 平衡树 问题,用 Treap 或 Splay 都可以。
但是我做这题用了4天。。。
第一天:(RE 0)*4
第二天:(RE 0)*2+(RE 60)*2
第三天:(WA 0)*2+(WA 40)*3
第四天:(WA 0)*1+(WA 40)*1+(AC 100)*1
实在是丧心病狂的题目。。。
注意:不要将 操作2 与 操作3 弄反,题目有毒。。。
附上苦心敲出的AC代码:
#include<iostream>#include<algorithm>#include<cstdio>using namespace std;struct node{node* son[2];int v,data,sum1,sum2,w;node(){son[0]=son[1]=NULL;w=rand();v=data=sum1=sum2=0;}};node* rt;inline int read(){int date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w;}void maintain(node* &u){u->sum1=u->v;u->sum2=u->data;if(u->son[0]!=NULL){u->sum1+=u->son[0]->sum1;u->sum2+=u->son[0]->sum2;}if(u->son[1]!=NULL){u->sum1+=u->son[1]->sum1;u->sum2+=u->son[1]->sum2;}}void turn(node* &u,int f){node* t=u->son[f^1];u->son[f^1]=t->son[f];t->son[f]=u;maintain(u);maintain(t);u=t;}bool insert(node* &u,int w,int c){if(u==NULL){u=new node;u->v=c;u->data=w;maintain(u);return true;}else if(u->v==c)return false;int y=c>u->v?1:0;bool f=insert(u->son[y],w,c);if(u->son[y]->w>u->w)turn(u,y^1);if(u!=NULL)maintain(u);return f;}void remove(node* &u,int x,int y){if(u==NULL)return;if(u->v==x){if(u->son[0]==NULL&&u->son[1]==NULL)u=NULL;else if(u->son[0]!=NULL&&u->son[1]!=NULL){if(u->son[0]->w>u->son[1]->w){turn(u,1);remove(u->son[1],x,y);}else{turn(u,0);remove(u->son[0],x,y);}}else{if(u->son[0]==NULL)u=u->son[1];else u=u->son[0];}if(u!=NULL)maintain(u);return;}u->sum1-=x;u->sum2-=y;if(x<u->v)remove(u->son[0],x,y);else if(x>u->v)remove(u->son[1],x,y);if(u!=NULL)maintain(u);}void find(node* u,int k,int &x,int &y){if(k)while(u->son[0]!=NULL)u=u->son[0];else while(u->son[1]!=NULL)u=u->son[1];x=u->v;y=u->data;}int main(){srand(987);int x,y,z,m=0;while(1){scanf("%d",&x);if(x==-1)break;if(x==1){scanf("%d%d",&y,&z);if(insert(rt,y,z))m++;continue;}if(m==0)continue;m--;find(rt,(x==3?1:0),y,z);remove(rt,y,z);}if(rt==NULL)printf("0 0\n");else printf("%d %d\n",rt->sum2,rt->sum1);return 0;}
原创粉丝点击