CF 19D - Points 线段树套平衡树
给出三种操作:
1.增加点(x,y)
2.删除点(x,y)
3.询问在点(x,y)右上方的点,如果有相同,输出最左边的,如果还有相同,输出最低的那个点
分析:
线段树套平衡树。
我们先离散化输入的x坐标,然后以每个坐标建立一棵平衡树来维护,这里可以直接用set或者map来维护就行了。
然后我们现在需要在x的右方找到最左最下大于(x,y)的点。
建立一棵线段树,维护的是区间的纵坐标的最值,而线段树的端点为离散后x的值。
1.我们每次插入的时候,直接在相应的平衡树中插入,然后更新一下线段树的区间最值。
2.删除时,直接删掉,更新一下最值。
3.询问时,对于整个区间,我们找到比x大的区间,利用区间最值,从左往右找是否存在大于y的点。最后输出即可。
具体看代码。。。
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> using namespace std; typedef long long ll;
typedef unsigned long long ull; #define debug puts("here")
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
#define pb push_back
#define RD(n) scanf("%d",&n)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
#define All(vec) vec.begin(),vec.end()
#define MP make_pair
#define PII pair<int,int> /******** program ********************/ const int MAXN = 2e5+5; int id[MAXN];
set<int> se[MAXN]; struct Data{
char op;
int x,y;
}d[MAXN]; struct node{
int l,r,mx;
inline int mid(){
return (l+r)>>1;
}
}tree[MAXN<<2]; void build(int l,int r,int rt){ // 建树
tree[rt].l = l;
tree[rt].r = r;
tree[rt].mx = -1;
if(l==r){
se[l].clear(); // 平衡树清空
return;
}
int mid = tree[rt].mid();
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
} void update(int x,int rt){ // 更新操作
if(tree[rt].l==tree[rt].r){
if(se[x].size()==0) // 如果为空
tree[rt].mx = -1;
else{
set<int>::iterator it = se[x].end(); // 最大值其实就是最后一个元素
tree[rt].mx = *--it;
}
return;
}
int mid = tree[rt].mid();
if(x<=mid) update(x,rt<<1);
else update(x,rt<<1|1);
tree[rt].mx = max(tree[rt<<1].mx,tree[rt<<1|1].mx);
} int ask(int x,int y,int rt){
if(tree[rt].l==tree[rt].r)
return tree[rt].l;
if( tree[rt<<1].r>x && tree[rt<<1].mx>y ){ // 如果左儿子区间存在比x大且最值大于y,可能在左儿子区间
int t = ask(x,y,rt<<1);
if(t!=-1) return t;
}
if( tree[rt<<1|1].mx>y ) // 这里右儿子的右端点显然比x大
return ask(x,y,rt<<1|1);
return -1;
} int main(){ #ifndef ONLINE_JUDGE
freopen("sum.in","r",stdin);
//freopen("sum.out","w",stdout);
#endif int n;
int ncase = 0;
while(cin>>n){
ncase?puts("----------------"):ncase = 1;
char op[10];
vector<int> vec;
rep1(i,n){
scanf("%s%d%d",op,&d[i].x,&d[i].y);
d[i].op = op[0];
vec.pb(d[i].x);
}
sort(All(vec));
vec.erase( unique(All(vec)),vec.end() ); // 去重
foreach(i,vec)
id[i] = vec[i];
int len = vec.size(); build(0,len+10,1); rep1(i,n){
int x = lower_bound(id,id+len,d[i].x)-id+1; // 二分出x离散后的值 int y = d[i].y;
if(d[i].op=='a'){
se[x].insert(y);
update(x,1);
}
else if(d[i].op=='r'){
se[x].erase(y);
update(x,1);
}
else{
int t = ask(x,y,1);
if(t==-1)
puts("-1");
else
printf("%d %d\n",id[t-1],*se[t].upper_bound(y)); // 二分出比y大的值
}
}
} return 0;
}
CF 19D - Points 线段树套平衡树的更多相关文章
- 【BZOJ-3196】二逼平衡树 线段树 + Splay (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2271 Solved: 935[Submit][Stat ...
- BZOJ3196二逼平衡树——线段树套平衡树(treap)
此为平衡树系列最后一道:二逼平衡树您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询 ...
- P3380 【模板】二逼平衡树(树套树)(线段树套平衡树)
P3380 [模板]二逼平衡树(树套树) 前置芝士 P3369 [模板]普通平衡树 线段树套平衡树 这里写的是线段树+splay(不吸氧竟然卡过了) 对线段树的每个节点都维护一颗平衡树 每次把给定区间 ...
- bzoj 3196/ Tyvj 1730 二逼平衡树 (线段树套平衡树)
3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description ...
- bzoj 2120 线段树套平衡树
先吐下槽,改了快一个小时,最后发现是SBT的delete写错了,顿时就有想死的心..... 首先对于这道题,我们应该先做一下他的小问题,bzoj1878,虽然和这道题几乎一点关系没有, 但是能给我们一 ...
- [BZOJ1146][CTSC2008]网络管理Network(二分+树链剖分+线段树套平衡树)
题意:树上单点修改,询问链上k大值. 思路: 1.DFS序+树状数组套主席树 首先按照套路,关于k大值的问题,肯定要上主席树,每个点维护一棵权值线段树记录它到根的信息. 关于询问,就是Que(u)+Q ...
- P3380 【模板】二逼平衡树(树套树) 线段树套平衡树
\(\color{#0066ff}{ 题目描述 }\) 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 查询k在区间内的排名 查询区间内排名为k的值 修改某一位值上 ...
- 树套树Day1线段树套平衡树bzoj3196
您需要写一种数据结构,来维护一个有序数列,其中需要提供以下操作:1.查询k在区间内的排名2.查询区间内排名为k的值3.修改某一位值上的数值4.查询k在区间内的前驱(前驱定义为小于x,且最大的数)5.查 ...
- BZOJ3196 二逼平衡树 【线段树套平衡树】
题目 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排名 2.查询区间内排名为k的值 3.修改某一位值上的数值 4.查询k在区间内的前驱(前驱 ...
随机推荐
- PC问题-(仅供备用)取消磁盘的自动扫描
问题现象:有一次整个单位停电了,之后再开机,每次电脑都自检.现在不想让电脑自检了. 问题原因:可能是因为停电,造成了系统文件的破坏. 问题处理:禁用电脑自检功能(注册表方法). Windows Reg ...
- Excel DNA学习笔记一
由于各种原因,被迫学习Excel DNA这个开源项目的使用方法,最后希望可以在其中,调用xll进行编码. 由此整理一下,这期间使用到的一些资料. 1.下载Excel DNA,目前最新的是0.30版 h ...
- window 下cygwin开启了后来又关闭了
特征: ssh localhost 出现port 27 拒绝访问等 系统日志记录信息: 事件 ID ( 0 )的描述(在资源( sshd )中)无法找到.本地计算机可能没有必要的注册信息或消息 DLL ...
- 【数据库】MySql常用函数梳理
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5866388.html MySql常用函数梳理: 1:数学函数 使用格式:一般用于插入.修改语句中,直接 函数( ...
- Kicad使用经验谈
最近开始学习使用Linux上的开源软件KiCad来绘制电路图和PCB.学习这个还是比较快的,用了两天了,觉得还是蛮方便的. 在这两天的使用以及今后的使用过程中,一定会有很多想要谈的.所以,就写下这篇博 ...
- Servlet 总结
1,什么是Servlet2,Servlet有什么作用3,Servlet的生命周期4,Servlet怎么处理一个请求5,Servlet与JSP有什么区别6,Servlet里的cookie技术7,Serv ...
- Fibonacci数列
问题描述 Fibonacci数列的递推公式为:Fn=Fn-1+Fn-2,其中F1=F2=1. 当n比较大时,Fn也非常大,现在我们想知道,Fn除以10007的余数是多少. 输入格式 输入包含一个整数n ...
- U3D中的协同等待函数
WaitForSeconds.WaitForseconds等待函数; 创建一个yield指令,来等待给定的秒数; using UnityEngine; using System.Collections ...
- Cocos2d-x——pthread的使用注意事项
1:多线程所调用的成员方法定义为static. 2:互斥锁(pthread_mutex_t)定义在cpp文件的开头,并且也定义为static. 3:pthread_mutex_init方法尽量在最早的 ...
- Java中单例设计模式总结
两种单例常见的实现方式: 1:懒汉的设计模式,在第一次调用的时候才完成相关的初始化操作 懒汉式是典型的时间换空间,就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间.当然,如果一直没有人 ...