题意:给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树)的更多相关文章

  1. UVa 11020 Efficient Solutions (BST)

    题意:给按顺序给定 n 个人群,用x和y来描述,如果有没有任何一个x' < x y' <= y 或 x '<= x y' <= y,那么这个群体就是优势群体, 让你求出每放入一 ...

  2. UVA 11020 - Efficient Solutions(set)

    UVA 11020 - Efficient Solutions 题目链接 题意:每个人有两个属性值(x, y).对于每个人(x,y)而言,当有还有一个人(x', y'),假设他们的属性值满足x' &l ...

  3. uva 11020 - Efficient Solutions ——平衡BST

    链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&am ...

  4. STL(multiset) UVA 11020 Efficient Solutions

    题目传送门 题意:训练指南P228 分析:照着书上的做法,把点插入后把它后面不占优势的点删除,S.size ()就是优势的人数,时间复杂度O (nlogn) #include <bits/std ...

  5. UVa 11020 Efficient Solutions(平衡二叉树/multiset )

    题意:有n个人,每个人有x.y两个属性,每次输入一个人(x,y).如果当前不存在一个人(x`,y`)的属性满足x`<=x,y`<y或者x`<x,y`<=y,就说这个人是有优势的 ...

  6. uva 11020 Efficient Solutions

    题意:给你n个人,有两个属性x.y,如果不存在另外一个人x2,y2满足 x2<=x,y2<y 或者 x2<x,y2<=y,那么就称这个人是有优势的,每次给你一个人得信息,问你当 ...

  7. UVA - 11020 Efficient Solutions(Multiset)

    本题利用multiset解决.根据题意,如果我们用P(x,y)表示一个人,因为人可以相同,所以用multiset.我们会发现,如果所有人群都是有优势的,那么这些点呈现一个递减的趋势.如果刚刚插入一个人 ...

  8. UVA 11020 Efficient Solutions+multiset的应用

    题目链接:点击进入 首先来讲,非常easy看到我们事实上仅仅要维护优势人群的集合:假设增加一个新的人,我们首先看一下优势人群中是否有人会让这个人失去优势,假设没有,则将这个人插入集合中.但要注意到这个 ...

  9. UVA 11922 Permutation Transformer (Splay树)

    题意: 给一个序列,是从1~n共n个的自然数,接下来又m个区间,对于每个区间[a,b],从第a个到第b个从序列中分离出来,翻转后接到尾部.输出最后的序列. 思路: 这次添加了Split和Merge两个 ...

随机推荐

  1. nodejs开发游戏服务器遇到的性能问题

    问题描述: 使用nodejs开发了一个游戏服务器,为了尽可能提高服务器的性能,服务器采用多进程的架构,前面处理玩家socket连接的是多个nodejs进程,使用 child_process 模块,服务 ...

  2. C:static 关键字、静态变量、跨类访问数据

    static 在OC中的使用 参考1   参考2   参考3   参保4    参考5 跨类访问成员 参考 +号方法就是类方法(静态方法),说明不用创建对象,可以直接通过类型去直接调用这个方法,在OC ...

  3. 使用AES128加密字符串

    import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.apache.c ...

  4. centos7添加新硬盘并挂载

    一.查看现有磁盘设备 fdisk -l 发现/dev/sdb 为新加的硬盘: 二.开始分区 fdisk /dev/sdb fdisk -l #再次查看分区情况,已经有了/dev/sdb1 三.创建文件 ...

  5. HDU 1713 相遇周期 (最小公倍数)

    题意:... 析:求周期就是这两个分数的最小公倍数,可以先通分,再计算分子的最小倍数. 代码如下: #pragma comment(linker, "/STACK:1024000000,10 ...

  6. 洛谷 - P5000 - Hillwer编码 - 高精度

    https://www.luogu.org/problemnew/show/P5000 第一次写一个正经的高精度题. 很明显ASCII码的乘积绝对是溢出的. 那么直接上Java.正好学一手Java的字 ...

  7. 力荐!35 个最好用的 Vue 开源库!

    无论是开发新手还是经验丰富的老手,我们都喜欢开源软件包.对于开发者来说,如果没有这些开源软件包,很难想象我们的生活会变得多么疲惫不堪,而且靠咖啡度日也会成为家常便饭.所幸的是,随着 Vue.js 和 ...

  8. Java笔记-序列化的注意点

    1.使用serialVersionUID 在Eclipse中,如果一个类实现了Serializable接口,且没有给这个类设置一个serialVersionUID,就会有一个警告标志: The ser ...

  9. springboot修改项目不需要重启服务器

    一.spring-boot-devtools 在pom中直接引入依赖 <dependency>        <groupId>org.springframework.boot ...

  10. Travelling HDU - 3001

    Travelling HDU - 3001 方法:3进制状态压缩dp(更好的方法是预处理出每个状态数字对应的y数组,然后用刷表,时间复杂度可以少一个n) #include<cstdio> ...