题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4441

题意:一个数列,三种操作:(1)插入:找到没在当前数列中的最小的正整数i,将其插在位置p之后,并将-i插入某个位置使得满足先进先出(i表示进,-i表示出),这个位置尽量靠右;(2)删除:删掉数字i以及-i;(3)询问:查询i和-i之间的数字的和。

思路:对于没在数列中的数字可以用一个set直接维护。i的插入是正常的splay操作。对于-i的插入,我们首先找到i之前有几个正数,比如有x个,那么-i必然是插在第x+1个负数的前面,因此在splay节点中要保存负数的个数。删除和查询都是splay正常操作。

struct node
{
	i64 sum;
	int val;
    int size[2];
	int Size;
    node *c[2],*p;

};

node a[N],*root,*nullNode;
int cnt;

void pushUp(node *p)
{
    if(p==nullNode) return;

	p->Size=1;
	p->sum=p->val;
	p->size[0]=p->size[1]=0;
	if(p->val>0) p->size[1]++;
	else if(p->val<0) p->size[0]++;

	if(p->c[0]!=nullNode)
	{
		p->Size+=p->c[0]->Size;
		p->sum+=p->c[0]->sum;
		p->size[0]+=p->c[0]->size[0];
		p->size[1]+=p->c[0]->size[1];
	}

	if(p->c[1]!=nullNode)
	{
		p->Size+=p->c[1]->Size;
		p->sum+=p->c[1]->sum;
		p->size[0]+=p->c[1]->size[0];
		p->size[1]+=p->c[1]->size[1];
	}
}

int ok(node *p)
{
    return p!=nullNode&&(p!=&a[1])&&(p!=&a[2]);
}

node *newNode(int val,node *p)
{
    node *e=&a[val>0?val:-val+100000];
    e->c[0]=e->c[1]=nullNode;
    e->p=p;
    e->Size=1;
	e->val=e->sum=val;
	e->size[0]=e->size[1]=0;

	if(val>0) e->size[1]++;
	else e->size[0]++;
    return e;
}

void init()
{
    nullNode=new node();
    nullNode->size[0]=nullNode->size[1]=0;
	nullNode->Size=0;
    nullNode->sum=0;
	nullNode->c[0]=nullNode->c[1]=nullNode->p=nullNode;

    root=new node();
	root->c[0]=root->c[1]=root->p=nullNode;
    root->sum=0;
	root->val=0;
	root->size[0]=root->size[1]=0;
	root->Size=1;

	root->c[1]=new node();
	root->c[1]->c[0]=root->c[1]->c[1]=nullNode;
	root->c[1]->p=root;
    root->c[1]->sum=root->c[1]->val=-1;
	root->c[1]->Size=1;
	root->c[1]->size[0]=root->c[1]->size[1]=0;
	root->c[1]->size[0]++;

    pushUp(root);

}

void zig(node *x)
{
    node *p=x->p,*q=p->p;
    p->c[0]=x->c[1];
    if(x->c[1]!=nullNode) x->c[1]->p=p;
    x->c[1]=p;
    p->p=x;
    x->p=q;
    if(q!=nullNode)
    {
        if(q->c[0]==p) q->c[0]=x;
        else q->c[1]=x;
    }
    pushUp(p);
    pushUp(x);
    if(root==p) root=x;
}

void zag(node *x)
{
    node *p=x->p,*q=p->p;
    p->c[1]=x->c[0];
    if(x->c[0]!=nullNode) x->c[0]->p=p;
    x->c[0]=p;
    p->p=x;
    x->p=q;
    if(q!=nullNode)
    {
        if(q->c[0]==p) q->c[0]=x;
        else q->c[1]=x;
    }
    pushUp(p);
    pushUp(x);
    if(root==p) root=x;
}

void splay(node *x,node *goal)
{
    while(x->p!=goal)
    {
        if(x->p->p!=goal)
        {
            if(x->p->p->c[0]==x->p)
            {
                if(x->p->c[0]==x) zig(x->p),zig(x);
                else zag(x),zig(x);
            }
            else
            {
                if(x->p->c[1]==x) zag(x->p),zag(x);
                else zig(x),zag(x);
            }
        }
        else
        {
            if(x->p->c[0]==x) zig(x);
            else zag(x);
        }
    }
}

void select(int k,node *goal)
{
    node *p=root;
    while(k!=p->c[0]->Size+1)
    {
        if(k<=p->c[0]->Size) p=p->c[0];
        else
        {
            k-=1+p->c[0]->Size;
            p=p->c[1];
        }
    }
	splay(p,goal);
}

int curNodeNum;

void insert(int p,int val)
{
    select(p,nullNode);
    select(p+1,root);
    node *e=newNode(val,root->c[1]);
    root->c[1]->c[0]=e;
    splay(e,nullNode);

	curNodeNum++;
}

node *getPre(node *u)
{
	splay(u,nullNode);
	u=u->c[0];
	while(u->c[1]!=nullNode) u=u->c[1];
	return u;
}
node *getNext(node *u)
{
	splay(u,nullNode);
	u=u->c[1];
	while(u->c[0]!=nullNode) u=u->c[0];
	return u;
}

node *getKth0(int k)
{
    node *p=root;
    while(1)
    {
        if(p->c[0]->size[0]>=k) p=p->c[0];
        else if(p->c[0]->size[0]+1==k)
        {
            if(p->val<0) return p;
            k-=p->c[0]->size[0];
            p=p->c[1];
        }
        else
        {
            k-=p->c[0]->size[0];
            if(p->val<0) k--;
            p=p->c[1];
        }
    }
}

void del(node *p)
{
	node *u=getPre(p);
	node *v=getNext(p);
	splay(u,nullNode);
	splay(v,root);
	root->c[1]->c[0]=nullNode;
	splay(root->c[1],nullNode);

	curNodeNum--;
}

set<int> S;
int n;

void deal()
{
	S.clear();
	init();

	curNodeNum=2;

	int i;
	for(i=1;i<=100000;i++) S.insert(i);
	while(n--)
	{
		char op[10];
		int p;
		scanf("%s%d",op,&p);
		if(op[0]=='i')
		{
			int t=*S.begin();
			S.erase(t);
			insert(p+1,t);

			splay(a+t,nullNode);
			int num=0;
			if(root->c[0]!=nullNode) num+=root->c[0]->size[1];
			if(root->val>0) num++;

			node *u=getKth0(num);

			node *v=getPre(u);
			splay(v,nullNode);
			splay(u,root);
			node *tmp=newNode(-t,root->c[1]);
			root->c[1]->c[0]=tmp;
			splay(tmp,nullNode);

			curNodeNum++;

		}
		else if(op[0]=='r')
		{
			S.insert(p);
			del(a+p);
			del(a+p+100000);
		}
		else
		{
			node *u=a+p;
			node *v=a+p+100000;
			splay(u,nullNode);
			splay(v,root);
			i64 sum=root->c[1]->c[0]->sum;
			output(sum); puts("");
		}
	}
}

int main()
{
	int num=0;
	while(scanf("%d",&n)!=-1)
	{
		printf("Case #%d:\n",++num);
		deal();
	}
}

HDU 4441 Queue Sequence(splay)的更多相关文章

  1. HDU 4441 Queue Sequence(优先队列+Treap树)(2012 Asia Tianjin Regional Contest)

    Problem Description There's a queue obeying the first in first out rule. Each time you can either pu ...

  2. HDU 1711 Number Sequence(数列)

    HDU 1711 Number Sequence(数列) Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Ja ...

  3. HDU 1005 Number Sequence(数列)

    HDU 1005 Number Sequence(数列) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Jav ...

  4. hdu 4915 Parenthese sequence(模拟)2014多培训学校5现场

    Parenthese sequence                                                                     Time Limit: ...

  5. hdu 6047 Maximum Sequence(贪心)

    Description Steph is extremely obsessed with "sequence problems" that are usually seen on ...

  6. HDU 4441 Queue Sequence

    http://acm.hdu.edu.cn/showproblem.php?pid=4441 题意:对于一个序列,每次有三种操作   insert pos  表示在pos插入一个数,这个数是最小的正数 ...

  7. HDU 1711 Number Sequence(KMP)附带KMP的详解

    题目代号:HDU 1711 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1711 Number Sequence Time Limit: 10000/ ...

  8. hdu 6299 Balanced Sequence (贪心)

    Balanced Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  9. HDU 1890 Robotic Sort(splay)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=1890 [题意] 给定一个序列,每次将i..P[i]反转,然后输出P[i],P[i]定义为当前数字i ...

随机推荐

  1. win7 64位系统下 PL/SQL无法连接的问题

    第一步:下载oracle客户端 由于 PLSQL Developer 没有64位版本,所以在64位系统上运行该程链接64位Oracle时就会报错,笔者为这个问题纠结了好几天,后来通过请教Google ...

  2. scrapy学习记录

    scrapy是一个用来爬取一个或多个网站的数据,提取数据的应用框架.下载过程非常复杂,而且会遇到各种问题.所以写个博客来记录下. 安装好python2.7之后,就可以开始.安装scrapy前还需要安装 ...

  3. mysql grant用户权限设置

    MySQL 赋予用户权限命令的简单格式可概括为: grant 权限 on 数据库对象 to 用户 一.grant 普通数据用户,查询.插入.更新.删除 数据库中所有表数据的权利. grant sele ...

  4. 【python cookbook】【数据结构与算法】6.在字典中将键映射到多个值上

    问题:一个能将键(key)映射到多个值的字典(即所谓的一键多值字典[multidict]) 解决方案:如果想让键映射到多值,需要将这多个值保持到另一个容器如列表或集合中: >>> d ...

  5. 理解Linux中断 (3)【转】

    转自:http://blog.csdn.net/tommy_wxie/article/details/7425712 版权声明:本文为博主原创文章,未经博主允许不得转载. .下半部 在中断处理过程中, ...

  6. docker stop 与 docker kill的区别

    docker stop 与 docker kill 均可以将容器停掉,但二者究竟有什么区别呢?首先,摘录一下官网对这两个功能的描述: docker stop: Stop a running conta ...

  7. ubunt1204安装配置vsftp

    本文将搭建一个最简单的ftp服务,即通过root用户可进行登录.上传.下载,具体步骤如下: 1.安装vsftpd服务 sudo apt-get install vsftpd 2.编辑vsftp配置文件 ...

  8. textarea 在浏览器中禁用拖动和固定大小

    HTML 标签 textarea 在大部分浏览器中只要指定行(rows)和列(cols)属性,就可以规定 textarea 的尺寸,大小就不会改变,不过更好的办法是使用 CSS 的 height 和 ...

  9. 微信开放平台API开发资料

    微信大概两年前开启了微信公众平台的API供开发者使用,从账号登陆.消息发送.用户账号管理.公众号菜单.客服接口.微信商店接口.用户卡券接口 以及微信支付接口.可以说是全方面覆盖了电商所需要的要素,与阿 ...

  10. 浅谈SQL中的单引号

    单引号:对很对计算机语言包括(SQL)是做字符串引用的:这个是大家通常知道的作用:但是对SQL语言来说:还有另外一个作用是作引号的转义 总结下:对oracle(sql)的作用. 做字符串引用:例如'a ...