Luogu P2073 送花

题目传送门

操作2和操作3反着写是什么鬼?反人类


权值线段树的模板题

然而AC后才发现,可以用( t{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;
}
原文地址:https://www.cnblogs.com/morslin/p/11854897.html