题目背景
小明准备给小红送一束花,以表达他对小红的爱意。他在花店看中了一些花,准备用它们包成花束。
题目描述
这些花都很漂亮,每朵花有一个美丽值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。
经典 平衡树 问题,用 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;
}