首页 > 其他分享 >P2073题解

P2073题解

时间:2023-08-16 17:13:51浏览次数:62  
标签:return val int 题解 tree P2073 root size

链接:P2073 送花

题意:

有若干朵花,每个有两个属性(美丽值和价格)。你需要维护 \(3\) 种操作:

  • 1.添加一朵花(如果之前有价格相同的忽略此操作)
  • 2.删除最贵的花
  • 3.删除最便宜的花
    最后输出两个数:美丽值的总和和价格总和

解法:

经典的平衡树题。
对于第一种操作,关键在于判重。先询问一下有没有价格相同的再加入。

bool ask(int &k,int val){//询问有没有价格为val的花
	bool flag=false;
	int a,b,z;
	a=b=z=0;
	split(k,a,b,val);
	split(a,a,z,val-1);//z树为价值为val的花
	if(z!=0) flag=true;
	merge(a,a,z);
	merge(k,a,b);
	return flag;
}

void insert(int &k,int val,int nice){
	int a,b;
	a=b=0;
	if(ask(root,val)) return;//先判重
	int cur=add_node(val,nice);
	split(k,a,b,val);
	merge(a,a,cur);
	merge(k,a,b);
	ans1+=val;
	ans2+=nice;
	return;
}

对于第二种和第三种操作,都是板子,但是不要忘记在删除之前判断一下树是否为空
全代码:

#include<bits/stdc++.h>
using namespace std;
int tot=0,root=0;
int ans1,ans2;

struct node{
	int lc,rc,size,val,rnk,nice;
}tree[100001];

void update(int k){
	tree[k].size=tree[tree[k].lc].size+tree[tree[k].rc].size+1;
	return;
}

void split(int k,int &a,int &b,int val){
	if(k==0){
		a=b=0;
		return;
	}
	else if(tree[k].val<=val){
		a=k;
		split(tree[k].rc,tree[k].rc,b,val);
	}
	else{
		b=k;
		split(tree[k].lc,a,tree[k].lc,val);
	}
	update(k);
	return;
}

void merge(int &k,int a,int b){
	if(a==0 || b==0){
		k=a+b;
		return;
	}
	else if(tree[a].rnk<tree[b].rnk){
		k=a;
		merge(tree[a].rc,tree[a].rc,b);
	}
	else{
		k=b;
		merge(tree[b].lc,a,tree[b].lc);
	}
	update(k);
	return;
}

int add_node(int val,int nice){
	tree[++tot].val=val;
	tree[tot].nice=nice;
	tree[tot].lc=tree[tot].rc=0;
	tree[tot].size=1;
	tree[tot].rnk=rand();
	return tot;
}

bool ask(int &k,int val){
	bool flag=false;
	int a,b,z;
	a=b=z=0;
	split(k,a,b,val);
	split(a,a,z,val-1);
	if(z!=0) flag=true;
	merge(a,a,z);
	merge(k,a,b);
	return flag;
}

void insert(int &k,int val,int nice){
	int a,b;
	a=b=0;
	if(ask(root,val)) return;
	int cur=add_node(val,nice);
	split(k,a,b,val);
	merge(a,a,cur);
	merge(k,a,b);
	ans1+=val;
	ans2+=nice;
	return;
}

void del(int &k,int val){
	int a,b,z;
	a=b=z=0;
	split(k,a,b,val);
	split(a,a,z,val-1);
	ans1-=tree[z].val;
	ans2-=tree[z].nice;
	merge(k,a,b);
}

int find_num(int k,int x){
	while(tree[tree[k].lc].size+1!=x){
		//cout<<k<<endl;
		if(tree[tree[k].lc].size>=x){
			k=tree[k].lc;
		}
		else{
			x-=(tree[tree[k].lc].size+1);
			k=tree[k].rc;
		}
	}
	return tree[k].val;
}

int main(){
	srand(time(0));
	int a,w,c;
	while(cin>>a){
		if(a==-1) goto to;
		else if(a==1){
			cin>>w>>c;
			insert(root,c,w);
		}
		else if(a==2){
			if(tree[root].size) del(root,find_num(root,tree[root].size));
		}
		else{
			if(tree[root].size) del(root,find_num(root,1));
		}
	}
	to:
	cout<<ans2<<" "<<ans1;
	return 0;
}

标签:return,val,int,题解,tree,P2073,root,size
From: https://www.cnblogs.com/wangwenhan/p/17635610.html

相关文章

  • 安防视频监控平台EasyNVR视频监控汇聚平台页面无法上传授权文件的问题解决方案
    TSINGSEE青犀视频安防监控平台EasyNVR可支持设备通过RTSP/Onvif协议接入,并能对接入的视频流进行处理与多端分发,包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等多种格式。在智慧安防等视频监控场景中,EasyNVR可提供视频实时监控直播、云端录像、云存储、录像检索与回看、告警等......
  • CF809E 题解
    一棵树,点权\(a_i(a_i\len)\),无边权,求\[\sum_{i\nej}\varphi(a_ia_j)\text{dis}(i,j)\]首先,你没有任何手段求\(10^{10}\)级别的一堆离散的\(\varphi\)。于是\[\varphi(xy)=\frac{\varphi(x)\varphi(y)\gcd(x,y)}{\varphi(\gcd(x,y))}\]然后一通莫反,枚举\(\gcd\)\[\sum......
  • CF1648E 题解
    就是\(m\)组询问补图的最小生成树上的树链最大值。有两种基本思路求这棵树。第一种,Kruskal,基于找到最小的边使两端点不连通。考虑补图中\((x,y)\)的边权,它是原图最小生成树上的树链最大值。从小到大枚举补图的边,相当于从小到大枚举原图最小生成树的边\((u,v,w)\),然后:令原图......
  • AT_agc064_a题解
    题面题目大意给定一个正整数\(N\),要求构造一个序列。对于每一个在\(1\)到\(N\)之间的整数\(i\),序列中包含了\(i\)个,并且将该序列首尾相接拼成环后,相邻两项之差大于等于\(1\)小于等于\(2\)。思路突破口是关于相邻两项之差的约束条件。(我一开始竟然只看见了“小于等......
  • CF1854D 题解
    CF1854DMichaelandHotel题解Links洛谷CodeforcesDescription这是一个交互题。有一个有\(n\)个点的内向基环树森林,zlsim位于\(1\)号节点,请你通过以下操作求出哪些节点(包括\(1\))可以通过从这两点开始沿边行走若干步汇至一点。给出两个参数\(u,k\)和点集\(S\),询......
  • P2034题解
    P2034题解题目描述给定一行\(n\)个非负整数\(a_1\cdotsa_n\)。现在你可以选择其中若干个数,但不能有超过\(k\)个连续的数字被选择。你的任务是使得选出的数字的和最大。题解正难则反,考虑将原问题转化为从\(a\)中选若干数使得,任意两数差不大于\(k\),求答案最小。观察......
  • ZS Shuffles Cards 题解
    ZSShufflesCards题解我们把每一次抽一些数字牌再抽到joker视作一局游戏。每局期望轮数首先考虑\(f_i\)表示每一局游戏抽出\(i\)张牌的概率。那么就是先抽出\(i-1\)张数字牌,再抽出一张joker。概率就是:\[f_i=\fracm{n+m-i+1}\prod_{k=0}^{i-2}......
  • CF1858A Buttons题解
    思路我们可以让两人先拿\(c\)里面的,因为\(a\)和\(b\)肯定是自己的,那么公共的“我”也要抢的越多越好,所以我们都要先拿\(c\)里面的。如果\(c\)是奇数,那么先手一定多拿\(1\)个\(c\)里面的,相当于先手可以拿\(a+1\)个,后手可以拿\(b\)个;如果\(c\)是偶数,那么两......
  • CF1858C Yet Another Permutation Problem 题解
    思路这个题是一个简单的构造题。竟然比T2简单,也是少见我们可以首先从\(1\)开始不断乘以\(2\),像这样:\(1,2,4,8,16\cdots,2^x\),直到什么时候超过\(n\)就停止。这样相邻两个数字就可以凑出\(1,2,4,6,\cdots,2^{x-1}\),保证两两不同。然后我们可以从\(3\)开始不......
  • 2023“钉耙编程”中国大学生算法设计超级联赛(9)- 1003 Reasoning 题解
    题目翻译基本符号有一推理系统,其中有这些符号:括号\((\)和\()\);逻辑连接词\(\lnot\)和\(\rightarrow\);全称量词\(\forall\);变量\(u\simz\);常量\(a\sime\);函数\(f\simh\);谓词\(P\simT\)。这些符号是构成系统的基础,他们之间能够组合出一些其他概念:项(term......