• [Luogu 2073] 送花


    <题目链接>

    很容易想到的平衡树,加个维护区间和。

    只需要插入和删除操作即可。

    kth其实都不用的,最小和最大可以从根节点log n一直向左/一直向右跑到叶子节点而求得。

    记得每插入完一个点一定要更新区间和!!更新区间和!!更新区间和!!

    我就因为没更新,导致出来答案都是随机的,有时候对,有时候不对。

    关于平衡树不多说啦,关于平衡树(Treap)的教程请看这里

    上代码。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    const int MAXN=100010;
    int n,w,x;
    class Treap
    {
    	public:
    		Treap(void)
    		{
    			rt=cnt=0;
    			memset(a,0,sizeof a);
    			memset(s,0,sizeof s);
    		}
    		void Insert(int w,int x)
    		{
    			_Insert(rt,w,x);
    		}
    		void Delete(bool l)
    		{
    			int i=Find(rt,l);
    			_Delete(rt,s[i].w,s[i].v);
    		}
    		void Answer(void)
    		{
    			printf("%d %d",s[rt].bty,s[rt].val);
    		}
    	private:
    		bool a[MAXN];
    		int rt,cnt;
    		struct node
    		{
    			int l,r,w,v,p,bty,val;
    		}s[MAXN];
    		int Random(void)
    		{
    			int x;
    			while(a[x=rand()%MAXN]);
    			a[x]=1;
    			return x;
    		}
    		void Update(int i)
    		{
    			s[i].bty=s[s[i].l].bty+s[s[i].r].bty+s[i].w;
    			s[i].val=s[s[i].l].val+s[s[i].r].val+s[i].v;
    		}
    		void L_Rotate(int &i)
    		{
    			int t=s[i].r;
    			s[i].r=s[t].l,s[t].l=i;
    			Update(i),Update(t),i=t;
    		}
    		void R_Rotate(int &i)
    		{
    			int t=s[i].l;
    			s[i].l=s[t].r,s[t].r=i;
    			Update(i),Update(t),i=t;
    		}
    		void _Insert(int &i,int w,int x)
    		{
    			if(!i)
    			{
    				s[i=++cnt].bty=s[i].w=w,s[i].val=s[i].v=x;
    				s[i].p=Random();
    				return;
    			}
    			if(x==s[i].v)
    				return;
    			if(x<s[i].v)
    			{
    				_Insert(s[i].l,w,x);
    				if(s[s[i].l].p>s[i].p)
    					R_Rotate(i);
    			}
    			else
    			{
    				_Insert(s[i].r,w,x);
    				if(s[s[i].r].p>s[i].p)
    					L_Rotate(i);
    			}
    			Update(i);//一定要更新!!
    		}
    		void _Delete(int &i,int w,int x)
    		{
    			if(!i)
    				return;
    			if(x==s[i].v)
    			{
    				if(!s[i].l || !s[i].r)
    					i=s[i].l | s[i].r;
    				else if(s[s[i].l].p>s[s[i].r].p)
    					R_Rotate(i),_Delete(i,w,x);
    				else
    					L_Rotate(i),_Delete(i,w,x);
    				return;
    			}
    			s[i].bty-=w,s[i].val-=x;
    			if(x<s[i].v)
    				_Delete(s[i].l,w,x);
    			else
    				_Delete(s[i].r,w,x);
    		}
    		int Find(int i,bool l)
    		{
    			if(l)
    				while(s[i].l)
    					i=s[i].l;
    			else
    				while(s[i].r)
    					i=s[i].r;
    			return i;
    		}
    }T;
    int main(int argc,char *argv[])
    {
    	srand((unsigned)time(NULL));
    	while(~scanf("%d",&n) && ~n)
    		switch(n)
    		{
    			case 1:
    				scanf("%d %d",&w,&x);
    				T.Insert(w,x);
    				break;
    			case 2:
    				T.Delete(0);
    				break;
    			case 3:
    				T.Delete(1);
    				break;
    		}
    	T.Answer();
    	return 0;
    }
    

    谢谢阅读

  • 相关阅读:
    修改表结构
    enum/set 约束
    MYSQL 数据类型
    表和数据的基础操作
    存储引擎
    mysql
    HTML 介绍
    selor模块
    select
    协程
  • 原文地址:https://www.cnblogs.com/Capella/p/8081874.html
Copyright © 2020-2023  润新知