Luogu P2073 送花
操作2和操作3反着写是什么鬼?反人类
权值线段树的模板题
然而AC后才发现,可以用\(\tt{set}\)水过……
权值线段树类似于用线段树来实现平衡树的一些操作,代码实现还是比较方便的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)
using namespace std;
struct zzz{
int w,c;
}tree[1000000<<2];
inline void up(int p){ //合并线段树的信息
tree[p].w=tree[ls].w+tree[rs].w;
tree[p].c=0;
if(tree[ls].w) tree[p].c+=tree[ls].c;
if(tree[rs].w) tree[p].c+=tree[rs].c;
}
void build(int l,int r,int p){ //初始化线段树
if(l==r){
tree[p].c=l; return ;
}
build(l,mid,ls); build(mid+1,r,rs);
}
void add(int l,int r,int p,int k,int f){ //添加一朵美丽值为f,价格为k的花
if(l==r){
if(tree[p].w) return ;
tree[p].w=f; return ;
}
else if(k<=mid) add(l,mid,ls,k,f);
else add(mid+1,r,rs,k,f);
up(p);
}
void del1(int l,int r,int p){ //去掉最便宜的花
if(l==r){
tree[p].w=0; return ;
}
if(tree[ls].w) del1(l,mid,ls);
else del1(mid+1,r,rs);
up(p);
}
void del2(int l,int r,int p){ //去掉最贵的花
if(l==r){
tree[p].w=0; return ;
}
if(tree[rs].w) del2(mid+1,r,rs);
else del2(l,mid,ls);
up(p);
}
int read(){
int k=0,f=1; char c=getchar();
for(;c<'0'||c>'9';c=getchar())
if(c=='-') f=-1;
for(;c>='0'&&c<='9';c=getchar())
k=k*10+c-48;
return k*f;
}
int main(){
build(1,1000001,1);
int k=read();
while(k!=-1){
if(k==1){
int w=read(),c=read();
add(1,1000001,1,c,w);
}
if(k==3) del1(1,1000001,1);
if(k==2) del2(1,1000001,1);
k=read();
}
cout<<tree[1].w<<" "<<tree[1].c;
return 0;
}