`
Coco_young
  • 浏览: 125584 次
  • 性别: Icon_minigender_1
  • 来自: 湖南长沙
社区版块
存档分类
最新评论

[平衡树]牛耳杯程序设计大赛决赛D题——BallIntheBox

 
阅读更多

题目描述:

BallsInTheBox

Timelimit:1sMemorylimit:32768kb

ProblemDescription

ThereareNboxesinStaginner’shouse,andwemarkthemby1,2,…,N.ThereareNi(1<=Ni<=10^4)ballsintheboxiinitially.NowStaginnerwilldosomeoperations,andhewillaskyousomesimplequestions.

Theoperationscontain:

1.Cij:takealltheballsintheboxiintotheboxjandthrowtheboxiaway,youcansurethatiisdifferentfromj.

2.Ain:addn(1<=n<=10^4)ballsintotheboxi.

3.Bin:taken(n>=0)ballsawayfromboxi,youcansurethatnisnotbiggerthanthenumberofballsintheboxi.

4.Qk:Staginneraskyouforthek-thsmallestnumberofballsinthebox,youcansurethatkisnotbiggerthanthetotalnumberofboxes.

Input:

Thereareseveraltestcases.

Thefirstlineofeachcasecontainstwointegers,N(1<=N<=10^5),M(1<=M<=10^5),indicatesthenumberofboxesandthenumberofoperations.ThenextlinecontainsNintegers,thei-thintegerindicatesthenumberofballsintheboxi.ThentherewillbeMlines,eachlinehasanoperationlikesomeoneoftheoperationsinthedescription.

Output:

Foreachtestcase,youneedonlyprintoneintegerforeachoperation“Qk”,indicatesthek-thsmallestnumberofballsinthebox.

SampleInput:

37

123

A31

C21

Q1

B34

Q1

C31

Q1

SampleOutput:

3

0

3

题目意思很简单,给定N个盒子和M个操作,然后给出初始时每个盒子里球的个数,接下来时M个操作,操作分为四种,

A a b :把编号为a的盒子里的球的数量增加b

B a b :把编号为a的盒子里的球的数量减少b

C a b :把编号为a的盒子里的球全倒进编号为b的盒子里,然后扔掉盒子a

Q k :查询球数第k小的盒子,对于每一个Q输出一行为该盒子里的球数

思路,如果用数组直接存,A B C 三个操作都容易实现,复杂度为O(1),然而Q操作每次都会花费O(n)的时间,n达到10^5,而且有10^5个询问,给定时限只有1s,肯定超时,于是想到用平衡二叉树来动态维护这些盒子,这样A B C D的时间复杂度都为O(logn),应该不会超时。

郁结的过程:比赛当时由于SBT不会写。。AVL写的不熟,然后果断放弃了该题,比赛之后弄到了题目和数据,自己在本地慢慢的搞,起初只用盒子里的球数来作为关键码,这样对于球数相同的情况是不能够处理了(经过旋转会破坏BST的性质),然后想到用盒子的球数和盒子的编号一起做关键码(球数为第一关键码,编号为第二关键码),这样就能够保证所有的关键码都不相同,于是终于AC了。 总算是把AVL写的比较熟练了。虽然代码风格比较挫。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100010;
//关键码结点类 
struct Node
{
   int wgt;
   int num;
   Node(int w=0,int n=0):wgt(w),num(n){}
   bool operator < (const Node &n) const
   {
        if(wgt!=n.wgt)return wgt<n.wgt;
        else return num<n.num;
   }   
   bool operator == (const Node &n) const
   {
        return wgt==n.wgt&&num==n.num;
   }
};
//AVL树 
struct AVLTree
{
   int l[MAXN],r[MAXN],size[MAXN],next[MAXN],h[MAXN],ROOT;
   Node Key[MAXN];
   int newnode(int w,int n)
   {
        int node = next[0];
        Key[node].wgt = w;
        Key[node].num = n;
        next[0] = next[node];
        h[node] = size[node] = 1;
        return node;
   }
   void delnode(int x)
   {
        next[x] = next[0];
        next[0] = x;
        Key[x].wgt = Key[x].num = h[x] = size[x] = l[x] = r[x] = 0;
   }
   void init()
   {
       for(int i=0;i<MAXN;i++)next[i]=i+1;
       memset(l,0,sizeof(l));
       memset(r,0,sizeof(r));
       memset(size,0,sizeof(size));
       memset(h,0,sizeof(h));
       ROOT = 0;
   }    
   void left_rotate(int &p)
   {
       int x = r[p];
       r[p] = l[x];
       l[x] = p;
       size[p] = size[l[p]]+size[r[p]]+1;
       size[x] = size[l[x]]+size[r[x]]+1;
       h[p] = max(h[l[p]],h[r[p]])+1;
       h[x] = max(h[l[x]],h[r[x]])+1;
       p = x;
   }
   void right_rotate(int &p)
   {
       int x = l[p];
       l[p] = r[x];
       r[x] = p;
       size[p] = size[l[p]]+size[r[p]]+1;
       size[x] = size[l[x]]+size[r[x]]+1;
       h[p] = max(h[l[p]],h[r[p]])+1;
       h[x] = max(h[l[x]],h[r[x]])+1;
       p = x;
   }
   void insert(int &p,Node k)
   {
        if(!p)
        {
              
            p = newnode(k.wgt,k.num);
            return;
        }
        if(k<Key[p])insert(l[p],k);
        else insert(r[p],k);
        h[p] = max(h[l[p]],h[r[p]])+1;
        size[p] = size[l[p]]+size[r[p]]+1;
        if(h[l[p]]-h[r[p]]==2)//L
        {
            if(h[l[l[p]]]>h[r[l[p]]])//LL
            {
                right_rotate(p);
            }
            else 
            {
                left_rotate(l[p]);
                right_rotate(p);
            }
        }
        else if(h[l[p]]-h[r[p]]==-2)//R
        {
            if(h[r[r[p]]]>h[l[r[p]]])//RR
            {
                left_rotate(p);
            }
            else 
            {
                right_rotate(r[p]);
                left_rotate(p);
            }
        }
   }
   int findmin(int &p)
   {
       if(l[p])return findmin(l[p]);
       return p;
   }
   void remove(int &p,Node k)
   {
       if(p)
       {
           if(k==Key[p])
           {
               if(!l[p])
               {
                   int x = p;
                   p = r[p];
                   delnode(x);
               }
               else if(!r[p])
               {
                   int x = p;
                   p = l[p];
                   delnode(x);
               }
               else
               {
                   int x = findmin(r[p]);
                   Key[p] = Key[x];
                   remove(r[p],Key[x]);
               }
           }
           else if(k<Key[p])remove(l[p],k);
           else remove(r[p],k);
           if(p)
           {
               h[p] = max(h[l[p]],h[r[p]])+1;
               size[p] = size[l[p]]+size[r[p]]+1;
           }
            if(h[l[p]]-h[r[p]]==2)//L
            {
                if(h[l[l[p]]]>h[r[l[p]]])//LL
                {
                    right_rotate(p);
                }
                else 
                {
                    left_rotate(l[p]);
                    right_rotate(p);
                }
            }
            else if(h[l[p]]-h[r[p]]==-2)//R
            {
                if(h[r[r[p]]]>h[l[r[p]]])//RR
                {
                    left_rotate(p);
                }
                else 
                {
                    right_rotate(r[p]);
                    left_rotate(p);
                }
            }
       } 
   }
   int Select(int p,int k)
   {
       int rank = size[l[p]]+1;
       if(rank==k)return p;
       else if(rank<k) return Select(r[p],k-rank);
       return Select(l[p],k);
   }
}avl;
int a[MAXN];
int main()
{
    int n,m;
    freopen("D.in","r",stdin);
    freopen("DansK2.out","w",stdout);
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        avl.init();
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)avl.insert(avl.ROOT,Node(a[i],i));
        for(int i=0;i<m;i++)
        {
            char op[5];int x,y;
            scanf("%s",op);
            if(op[0]=='A')
            {
                scanf("%d%d",&x,&y);
                avl.remove(avl.ROOT,Node(a[x],x));
                a[x]+=y;
                avl.insert(avl.ROOT,Node(a[x],x));
            }
            else if(op[0]=='B')
            {
                scanf("%d%d",&x,&y);
                avl.remove(avl.ROOT,Node(a[x],x));
                a[x]-=y;
                avl.insert(avl.ROOT,Node(a[x],x));
            }
            else if(op[0]=='C')
            {
                scanf("%d%d",&x,&y);
                avl.remove(avl.ROOT,Node(a[x],x));
                avl.remove(avl.ROOT,Node(a[y],y));
                a[y]+=a[x];
                avl.insert(avl.ROOT,Node(a[y],y));
            }
            else
            {
                scanf("%d",&x);
                printf("%d\n",avl.Key[avl.Select(avl.ROOT,x)].wgt);
            }
        }
    }
    return 0;
}


分享到:
评论

相关推荐

    牛耳教育XML课件,牛耳教育XML课件

    4. DOM(Document Object Model):XML文档的树形结构,提供了访问和操作XML数据的方法。 5. XML与数据库的交互:如何使用XML作为存储和检索数据的方式,以及与SQL数据库的集成。 6. SOAP(Simple Object Access ...

    Linux牛耳学习课件

    【Linux牛耳学习课件】是一份集合了嵌入式设计领域的精华教学资源,由知名的IT教育机构牛耳教育的特技讲师成老师倾力打造。这份课件旨在帮助学员深入理解和掌握Linux操作系统以及C语言编程,对于想要在IT行业,特别...

    牛耳教育Oracle课件,牛耳教育Oracle课件

    9. **数据库连接**:通过JDBC(Java Database Connectivity)或其他API,如ODBC,可以实现应用程序与Oracle数据库的连接和通信。 10. **Oracle RAC(Real Application Clusters)**:Oracle的集群解决方案,允许多...

    牛耳软件教育内部测试课件

    【牛耳软件教育内部测试课件】是一套全面且深入的测试...同时,这份【牛耳软件教育内部测试课件】还可能包含实战案例和练习题,帮助学习者将理论知识转化为实际操作技能,为他们在软件测试领域的发展打下坚实基础。

    牛耳培训管理系统软件

    《牛耳培训管理系统软件——构建高效教育管理的智慧之选》 牛耳培训管理系统软件,作为一款专为培训学校设计的高效管理工具,其核心功能在于优化教育资源分配,提升教学管理效率,确保学校运营的顺畅与高效。这款...

    牛耳教育之Jsp课件(080815A)

    互联网最初设计是为了能提供一个通讯网络,最初的网络是给计算机专家、 工程师和科学家用来做一些交流,当时的网络一点也不友好,那时候还没有家庭 和办公计算机,任何一个人用它,无论是计算机专家,工程师还是科学...

    java牛耳学生选课系统

    Java牛耳学生选课系统是一个专门为教育机构设计的信息化管理平台,它能够高效地帮助学生进行选课操作,同时也为教师和管理员提供了便捷的课程管理功能。该系统在Java编程语言的基础上构建,充分体现了Java的跨平台性...

    牛耳嵌入式liunx 系统编程源码

    《牛耳嵌入式Linux系统编程源码解析》 在嵌入式开发领域,Linux操作系统因其开源、稳定、高效的特点,被广泛应用于各种硬件平台。本资料“牛耳嵌入式Linux系统编程源码”正是针对这一领域的学习者提供的一份宝贵...

    牛耳微信引流软件1.2.4.1

    简介:牛耳微信引流软件是一款微信推广工具,本软件以官方原版为基础,通过模式方式,实现微信的开放式营销。 牛耳微信引流软件,以不修改任何原版为基础,通过100%模拟人工方式,做到批量实现手动引流。软件全自动...

    安博牛耳C语言强化训练资料

    7. 平衡二叉树:一种自平衡的二叉搜索树,例如AVL树或红黑树,保证任何节点的两个子树的高度差不超过1,从而保证了查找效率。 8. 堆栈溢出:由于栈空间有限,当分配的栈空间不足以存储新分配的数据时,就会发生堆栈...

    牛耳教育长沙Web大前端每天5道面试题.pdf

    【瀑布流布局】是Web前端开发中常见的网页布局方式,尤其在展示图片或者商品时非常流行。这种布局的特点是每个元素的宽度固定,但高度不一,形成类似瀑布的效果,新元素会填充到前一列的底部。实现瀑布流布局的基本...

    精选题1.doc

    1. **摩擦力与平衡**:问题1中提到的杆CD受到摩擦力和自身重力的平衡,涉及到静力学中的力平衡原理,需要计算摩擦力的分布来确定杆的轴向力。 2. **应力状态**:问题2探讨了低碳钢拉伸试验中的应力公式适用范围,...

    牛耳微信引流软件1.1.9.1

    【牛耳微信引流软件1.1.9.1】是一款专为微信用户设计的引流工具,主要用于提升微信营销效率和用户体验。本次更新至1.1.9.1版本,主要针对三个方面进行了优化和修复,分别是微信运行卡顿问题、地图功能以及通讯录模式...

    谁执全球电动汽车牛耳.pdf

    谁执全球电动汽车牛耳.pdf

    ResShare 2009 最优秀作品开源(牛耳教育)

    《ResShare 2009 最优秀作品开源:牛耳教育的P2P资源共享系统》 牛耳教育作为中国IT职业教育的重要机构,以其严谨的教学态度和高质量的教育资源著称。在2009年,湖南省牛耳教育新校区的一群学子们创作了一个名为...

    牛耳微信引流软件1.2.1.1

    【牛耳微信引流软件1.2.1.1】是一款专为微信营销设计的工具,其最新版本1.2.1.1带来了显著的改进和更新。以下将详细阐述这款软件的重要知识点: 首先,更新模拟器至6.2.8.5是这次升级的核心部分。模拟器通常用于在...

    长沙牛耳周毅老师课件1(ASP.NET)

    【ASP.NET】是一种基于微软.NET Framework的Web应用程序开发平台,由微软公司推出,旨在简化Web应用的构建和维护。ASP.NET提供了丰富的服务器控件、事件驱动模型和自动页面生命周期管理,使得开发者能够更加高效地...

    Linux欲执安全牛耳.pdf

    《Linux欲执安全牛耳》这篇文档探讨了操作系统安全性的议题,特别关注了Linux与Windows在安全性方面的比较。一直以来,Linux被广泛认为比Windows更安全,因为它的开源特性使得漏洞可以更快地被发现和修复。然而,...

    牛耳培训linux_app的代码和一个bbs项目源码

    【标题】"牛耳培训linux_app的代码和一个bbs项目源码" 涵盖了两个主要的知识点:Linux应用程序开发以及BBS(Bulletin Board System,电子公告板系统)的源码分析。 Linux应用程序开发是IT领域中的一个重要分支,它...

Global site tag (gtag.js) - Google Analytics