UVA 11020 Efficient Solutions (BST,Splay树)
题意:给n个坐标。一个坐标(x,y)若有无存在的坐标满足x1<x && y1<=y 或 x1<=x && y1<y 时,此坐标(x,y)是就是有优势的。在给每一个坐标之后,立刻输出当前有优势的坐标有多少个。
思路:Set可以做,但是我用Splay树实现也不难。观察题意中的不等式发现,一个点(x,y)的左下方不能有点(相当于跟(0,0)组成的矩形中不能有其他点,除了(x,y)之外),但是若有相同的点的存在,这些相同点都是优势点。
用Splay维护剩下的全部优势点,对于新来的一个点,如果它本来就被其他已经存在的优势点所淘汰,则不必插入树了。若没有被淘汰,插入它后,它有可能会淘汰其他点,如果我们根据x坐标来排序的话,有可能被淘汰的点就在新插入的点的右边,只要右边有点(x1,y1)满足y1>=y就会淘汰掉该点。
#include <bits/stdc++.h>
#define pii pair<int,int>
#define INF 0x3f7f7f7f
#define LL long long
using namespace std;
const int N=;
const int mod=; struct node
{
int key, y, pre, flip, ch[], son[];
}nod[N];
int n, node_cnt, root; int create_node(int v,int y,int far) //以x来排序即可。
{
nod[node_cnt].key=v;
nod[node_cnt].y=y;
nod[node_cnt].pre=far;
nod[node_cnt].flip=;
nod[node_cnt].ch[]=;
nod[node_cnt].ch[]=;
nod[node_cnt].son[]=;
nod[node_cnt].son[]=;
return node_cnt++;
} void Rotate(int t,int d)
{
int son=nod[t].ch[d];
int far=nod[t].pre;
int gra=nod[far].pre; nod[son].pre=far;
nod[far].pre=t;
nod[t].pre=gra; nod[t].ch[d]=far;
nod[far].ch[d^]=son;
nod[gra].ch[ nod[gra].ch[]==far ]=t; nod[far].son[d^]=nod[t].son[d];
nod[t].son[d]+=nod[far].son[d]+;
} int Insert(int t,int v,int y)
{
if(t==) return root=create_node(v, y, );
if( v==nod[t].key ) //x相同,必有人被淘汰
{
if(nod[t].y<y) return ; //此人无效
if(nod[t].ch[]) return Insert(nod[t].ch[], v, y); //插在其前面
else return nod[t].ch[]=create_node(v, y, t);
}
else if( v<nod[t].key )
{
if(nod[t].ch[]) return Insert(nod[t].ch[], v, y);
else return nod[t].ch[]=create_node(v, y, t);
}
else
{
if(nod[t].ch[]) return Insert(nod[t].ch[], v, y);
else return nod[t].ch[]=create_node(v, y, t);
}
} void Splay(int t,int goal)
{
while(nod[t].pre!=goal)
{
int f=nod[t].pre, g=nod[f].pre;
if(g==goal) Rotate(t, nod[f].ch[]==t);
else
{
int d1=nod[f].ch[]==t, d2=nod[g].ch[]==f;
if(d1==d2) Rotate(f, d1),Rotate(t, d1);
else Rotate(t, d1),Rotate(t, d2);
}
}
if(!goal) root=t;
} int Find_del_node(int t,int y)
{
if(t==) return ; //无后继了
if(nod[t].y>=y ) return t;
int q;
if(nod[t].ch[] && (q=Find_del_node(nod[t].ch[], y)) ) return q;
if(nod[t].ch[] && (q=Find_del_node(nod[t].ch[], y)) ) return q;
return ;
} int Find_bac(int t,int d) //这个可以找前驱也可以找后继。d为1则前驱。
{
if(t==) return ;
if(nod[t].ch[d]==) return t;
else return Find_bac(nod[t].ch[d], d);
} void Delete(int t) //专门删除根节点
{
int L=nod[t].ch[], R=nod[t].ch[];
if(R==) //无后继
{
root=L;
nod[root].pre=;
}
else //找后继
{
R=Find_bac(R, );
Splay( R, root);
nod[R].ch[]=L;
nod[R].pre=;
nod[R].son[]=nod[L].son[]++nod[L].son[];
nod[L].pre=R;
root=R;
}
} int main()
{
//freopen("input.txt", "r", stdin);
int t, k, a, b, ans, Case=;
cin>>t;
while(t--)
{
printf("Case #%d:\n", ++Case);
node_cnt=;
root=;
scanf("%d",&n);
for(int i=; i<n; i++)
{
scanf("%d%d", &a, &b);
int ok=Insert(root, a, b);
if(ok!=) //碰到x相同的,而且y又比它大,那么直接无效。但是并不是一定是优势点。
{
Splay(ok, ); //插入成功,先伸展到根。
int r=Find_bac(nod[root].ch[], ); //找前驱
if( r && nod[r].key<a && b>=nod[r].y) Delete(root); //新点为非优势点
else
{
while( (k=Find_del_node(nod[root].ch[], b))!= ) //从右边开始,找到一个删一个。
{
Splay(k, );
Delete(root);
Splay(ok, );
}
}
}
printf("%d\n", nod[root].son[]++nod[root].son[]); //输出树上有多少点
}
if(t) printf("\n");
}
return ;
}
AC代码
UVA 11020 Efficient Solutions (BST,Splay树)的更多相关文章
- UVa 11020 Efficient Solutions (BST)
题意:给按顺序给定 n 个人群,用x和y来描述,如果有没有任何一个x' < x y' <= y 或 x '<= x y' <= y,那么这个群体就是优势群体, 让你求出每放入一 ...
- UVA 11020 - Efficient Solutions(set)
UVA 11020 - Efficient Solutions 题目链接 题意:每个人有两个属性值(x, y).对于每个人(x,y)而言,当有还有一个人(x', y'),假设他们的属性值满足x' &l ...
- uva 11020 - Efficient Solutions ——平衡BST
链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&am ...
- STL(multiset) UVA 11020 Efficient Solutions
题目传送门 题意:训练指南P228 分析:照着书上的做法,把点插入后把它后面不占优势的点删除,S.size ()就是优势的人数,时间复杂度O (nlogn) #include <bits/std ...
- UVa 11020 Efficient Solutions(平衡二叉树/multiset )
题意:有n个人,每个人有x.y两个属性,每次输入一个人(x,y).如果当前不存在一个人(x`,y`)的属性满足x`<=x,y`<y或者x`<x,y`<=y,就说这个人是有优势的 ...
- uva 11020 Efficient Solutions
题意:给你n个人,有两个属性x.y,如果不存在另外一个人x2,y2满足 x2<=x,y2<y 或者 x2<x,y2<=y,那么就称这个人是有优势的,每次给你一个人得信息,问你当 ...
- UVA - 11020 Efficient Solutions(Multiset)
本题利用multiset解决.根据题意,如果我们用P(x,y)表示一个人,因为人可以相同,所以用multiset.我们会发现,如果所有人群都是有优势的,那么这些点呈现一个递减的趋势.如果刚刚插入一个人 ...
- UVA 11020 Efficient Solutions+multiset的应用
题目链接:点击进入 首先来讲,非常easy看到我们事实上仅仅要维护优势人群的集合:假设增加一个新的人,我们首先看一下优势人群中是否有人会让这个人失去优势,假设没有,则将这个人插入集合中.但要注意到这个 ...
- UVA 11922 Permutation Transformer (Splay树)
题意: 给一个序列,是从1~n共n个的自然数,接下来又m个区间,对于每个区间[a,b],从第a个到第b个从序列中分离出来,翻转后接到尾部.输出最后的序列. 思路: 这次添加了Split和Merge两个 ...
随机推荐
- solr安装-tomcat+solrCloud构建稳健solr集群
solrCloud的搭建可以有两种方式:使用solr内嵌的jetty来搭建:使用外部web容器tomcat来搭建.对于使用jett来搭建参考solr官方的手册照着做肯定ok,下面我主要讲的是如何使用t ...
- codeforces 691D D. Swaps in Permutation(dfs)
题目链接: D. Swaps in Permutation time limit per test 5 seconds memory limit per test 256 megabytes inpu ...
- Ordered Fractions
链接 分析:遍历一下,求个gcd即可,最后按照ans排序并去重 /* PROB:frac1 ID:wanghan LANG:C++ */ #include "iostream" # ...
- 平衡二叉树、B树、B+树、B*树、LSM树简介
平衡二叉树是基于分治思想采用二分法的策略提高数据查找速度的二叉树结构.非叶子结点最多只能有两个子结点,且左边子结点点小于当前结点值,右边子结点大于当前结点树,并且为保证查询性能增增删结点时要保证左右两 ...
- 洛谷 - P2280 - 激光炸弹
https://www.luogu.org/problemnew/show/P2280 二维前缀和差分的模板题.注意学习二维前缀和的求法,不用又down又right的. #include<bit ...
- 51nod 1094 【水题】
暴力即可!!! #include <stdio.h> #include <string.h> #include <iostream> using namespace ...
- Cocos2d-html5游戏开发,常用工具集合
代码编辑器IDEWebStorm (Windows, Mac) Cocos2d-html5官方团队在用,非常优秀的工具,请大家支持正版动画编辑器 Animation EditorSpriteHelpe ...
- MyEclipse中安装SVN插件的最有效的方法
(1)下载svn插件:http://subclipse.tigris.org/files/documents/906/49209/site-1.8.8.zip (2)解压svn包,找到其中的两个文件夹 ...
- [BZOJ4064/Cerc2012]The Dragon and the knights
Description 与当地鞋匠协会发生冲突的瓦维尔城堡的龙决定将它的狩猎场移出克拉科夫以减少敌对的邻居数量.现在他正在给和平而宁静的Bytes王国带来灾难与恐怖. 在Bytes王国有n条河流,每一 ...
- HTML5实现页面自动跳转
初学H5,书上说的是<meta http-equiv="refresh" content="5“ url=”./error.html"/>这样可以实 ...