操作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; }