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在区间内的前驱(前驱 ...
随机推荐
- Codeforces Round #332 (Div. 二) B. Spongebob and Joke
Description While Patrick was gone shopping, Spongebob decided to play a little trick on his friend. ...
- ssh使用ajax异步通讯. json与对象转换的几个小问题
首先是hibernate,用ssh做项目的时候,使用hibernate,这个hibernate博大精深,至今只懂皮毛.建对象时候使用它的一对多,多对多联系,. 这样子,对象转json的时候会产生循环依 ...
- HttpContext讲解
http://www.cnblogs.com/scy251147/p/3549503.html http://www.360doc.com/content/14/0526/10/17655805_38 ...
- U3D中的协同等待函数
WaitForSeconds.WaitForseconds等待函数; 创建一个yield指令,来等待给定的秒数; using UnityEngine; using System.Collections ...
- window.showModalDialog基础
本文转载:http://www.cnblogs.com/sunnycoder/archive/2010/05/05/1728047.html 基本知识 l showModalDialog() (IE ...
- URAL 1779 F - The Great Team 构造
F - The Great TeamTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest ...
- uva216 c++回溯法
因为题目要求最多8台电脑,所以可以枚举全排列,然后依次计算距离进行比较,枚举量8!=40320并不大,但这种方法不如回溯法好,当数据再大一些枚举就显得笨拙了,所以这个题我用回溯法做的,回溯有一个好处是 ...
- 设计一个算法,输出从u到v的全部最短路径(採用邻接表存储)
思想:用path数组存放路径(初始为空),d表示路径长度(初始为-1),查找从顶点u到v的最短路径过程如图所看到的: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5u ...
- JAXB完毕XML与Java对象的互转
这段时间都老忙了,甚至连周末全部人员都在赶产品的进度,想想连续上12天班,人都有点晕了! 到这会儿最终有点时间.所以准备和大家分享一下JAXB,会不会有人认为有点陌生呢?没事,这里跟大伙儿简单的描写叙 ...
- debian7编译内核
第一个步骤“配置内核”. 在这里,我比较建议在发行版默认的config的基础上再进行配置,这样 配置出的内核和发行版本身才会有更好的相容性.比如可以在运行“make menuconfig”之前执行命令 ...