传送门

Description

在一个笛卡尔坐标系中,定义三种操作:

\(add(x,y)\),将点\((x,y)\)标记在坐标系上

\(find(x,y)\),查询点\((x,y)\)严格右上方中,横坐标最小的点。如果有多个,输出其中纵坐标最小的。没有则输出-1

\(remove(x,y)\),将点\((x,y)\)取消标记

Input

第一行是操作个数\(n\)。

下面\(n\)行,每行对应一个操作。

Output

每个查询操作输出一个答案。

Hint

\(n~\leq~10^5,|x|,|y|~\leq~10^9\)。数据保证合法。

Solution

\(x,y\)这么大,先给他离散化再说。

考虑一个笛卡尔坐标系上,对每个横坐标\(x\)任取一个\(y\)组成点\((x,y)\),是与一个数列\(A\)有一一对应关系的。即,点\((x,y)\)对应序列\(A_x=y\)。

考虑对于一次查询,一列能做为答案的必要条件是这一列上\(y\)轴最大的点大于被查询的点的纵坐标。于是就想到将每个\(x\)对应的最大的\(y\)写入序列。于是每次查询时在序列上查询大于\(x\)的后缀上第一个大于\(y\)的位置的下标。这个显然可以用线段树搞定。考虑剩下的\(y\)怎么记录。使用线段树可以查询出应该被选择的横坐标。则纵坐标就是这一列上大于\(y\)的第一个数。于是对于每一列开一个\(set\),维护这一列上所有的\(y\),查询时直接upper_bound即可。

考虑线段树的写法。对于线段树的一个区间,维护这段区间中最大值的下标是多少。查询时,先递归查询左区间,如果左区间不合法则递归查询右区间。一个区间不合法当且仅当他与被查询的区间无交或他的最大值小于被查询的值\(k\)。

考虑这么做的复杂度:因为一个区间会被线段树划分成\(O(log(len))\)个线段。发现这些遍历这些线段是\(O(log)\)的,于是一次操作的复杂度是\(O(log)\)的。总复杂度\(O(nlogn)\)

Code

#include<set>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rg register
#define ci const int
#define cl const long long typedef long long int ll; template <typename T>
inline void qr(T &x) {
rg char ch=getchar(),lst=' ';
while((ch > '9') || (ch < '0')) lst=ch,ch=getchar();
while((ch >= '0') && (ch <= '9')) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
if(lst == '-') x=-x;
} namespace IO {
char buf[120];
} template <typename T>
inline void qw(T x,const char aft,const bool pt) {
if(x < 0) {x=-x,putchar('-');}
rg int top=0;
do {IO::buf[++top]=x%10+'0';} while(x/=10);
while(top) putchar(IO::buf[top--]);
if(pt) putchar(aft);
} template <typename T>
inline T mmax(const T a,const T b) {return a > b ? a : b;}
template <typename T>
inline T mmin(const T a,const T b) {return a < b ? a : b;}
template <typename T>
inline T mabs(const T a) {return a < 0 ? -a : a;} template <typename T>
inline void mswap(T &_a,T &_b) {
T _temp=_a;_a=_b;_b=_temp;
} const int maxn = 200010;
const int maxt = 1600010; struct M {
int opt,x,y;
};
M MU[maxn]; int n,tcnt,num;
int temp[maxt],CU[maxt];
std::set<int>ss[maxt]; struct Tree {
int v;
inline void update(const Tree &_ls,const Tree _rs) {
if(!(~(_ls.v))) this->v = _rs.v;
else if(!(~(_rs.v))) this->v = _ls.v;
else {
if(CU[_ls.v] >= CU[_rs.v]) this->v=_ls.v;
else this->v=_rs.v;
}
}
};
Tree tree[maxt]; void init_hash();
void change(ci,ci,ci,ci);
int ask(ci,ci,ci,ci,ci); int main() {
qr(n);
for(rg int i=1;i<=n;++i) {
M &now=MU[i];
rg char ch=getchar();
while((ch > 'z') || (ch < 'a')) ch=getchar();
if(ch == 'a') now.opt=1;
else if(ch == 'r') now.opt=3;
else now.opt=2;
qr(now.x);qr(now.y);
temp[++tcnt]=now.x;temp[++tcnt]=now.y;
}
init_hash();
memset(tree,-1,sizeof tree);
for(rg int i=1;i<=n;++i) {
M &now=MU[i];
switch(now.opt) {
case 1: {
ss[now.x].insert(now.y);
if(now.y == *(--ss[now.x].end())) {CU[now.x]=now.y;change(1,num,1,MU[i].x);}
break;
}
case 2: {
int k=ask(1,num,1,now.x+1,now.y);
if(!(~k)) {puts("-1");break;}
qw(temp[k],' ',true);
std::set<int>::iterator zay = ss[k].upper_bound(now.y);
qw(temp[*zay],'\n',true);
break;
}
case 3: {
if(now.y == *(--ss[now.x].end())) {
ss[now.x].erase(now.y);
if(ss[now.x].empty()) CU[now.x]=0;
else CU[now.x]=*(--ss[now.x].end());
change(1,num,1,MU[i].x);
}
else ss[now.x].erase(now.y);
break;
}
}
}
return 0;
} void init_hash() {
std::sort(temp+1,temp+1+tcnt);s
int *ed=std::unique(temp+1,temp+1+tcnt);
num=ed-temp-1;
for(rg int i=1;i<=n;++i) {
MU[i].x=std::lower_bound(temp+1,ed,MU[i].x)-temp;
MU[i].y=std::lower_bound(temp+1,ed,MU[i].y)-temp;
}
} void change(ci l,ci r,ci p,ci aim) {
if(l > r) return;
if((l > aim) || (r < aim)) return;
if(l == r) {tree[p].v=l;return;}
int mid=(l+r)>>1,dp=p<<1,ddp=dp|1;
change(l,mid,dp,aim);change(mid+1,r,ddp,aim);
tree[p].update(tree[dp],tree[ddp]);
} int ask(ci l,ci r,ci p,ci aim,ci v) {
if(l > r) return -1;
if(r < aim) return -1;
if(!(~(tree[p].v))) return -1;
if(CU[tree[p].v] <= v) return -1;
if(l == r) return tree[p].v;
int mid=(l+r)>>1,dp=p<<1,ddp=dp|1;
if(mid >= r) return ask(l,mid,dp,aim,v);
else if(mid < l) return ask(mid+1,r,ddp,aim,v);
else {
int _ans;
if(~(_ans=ask(l,mid,dp,aim,v))) return _ans;
else return ask(mid+1,r,ddp,aim,v);
}
}

Solution

一个笛卡尔坐标系中对于每一个横坐标\(x\)选择一个纵坐标\(y\)后,可以将之一一对应到一个下标为\(x\),值为\(y\)的线段上。利用这个性质可以将坐标问题改为序列修改问题使用数据结构处理。

【线段树】【CF19D】 Points的更多相关文章

  1. UVA10869 - Brownie Points II(线段树)

    UVA10869 - Brownie Points II(线段树) 题目链接 题目大意:平面上有n个点,Stan和Ollie在玩游戏,游戏规则是:Stan先画一条竖直的线作为y轴,条件是必需要经过这个 ...

  2. Codeforces 1140F Extending Set of Points 线段树 + 按秩合并并查集 (看题解)

    Extending Set of Points 我们能发现, 如果把x轴y轴看成点, 那么答案就是在各个连通块里面的x轴的个数乘以y轴的个数之和. 然后就变成了一个并查集的问题, 但是这个题目里面有撤 ...

  3. CodeForces 19D Points (线段树+set)

    D. Points time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  4. [hdu4347]The Closest M Points(线段树形式kd-tree)

    解题关键:kdtree模板题,距离某点最近的m个点. #include<cstdio> #include<cstring> #include<algorithm> ...

  5. CodeForces19D:Points(线段树+set(动态查找每个点右上方的点))

    Pete and Bob invented a new interesting game. Bob takes a sheet of paper and locates a Cartesian coo ...

  6. Codeforces Beta Round #19D(Points)线段树

    D. Points time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...

  7. 2019牛客多校第一场 I Points Division(动态规划+线段树)

    2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...

  8. CodeForces 19D Points(线段树+map)

    开始想不通,后来看网上说是set,就有一个想法是对每个x建一个set...然后又想直接建立两重的set就好,最后发现不行,自己想多了...  题意是给你三种操作:add (x y) 平面添加(x y) ...

  9. CF 19D - Points 线段树套平衡树

    题目在这: 给出三种操作: 1.增加点(x,y) 2.删除点(x,y) 3.询问在点(x,y)右上方的点,如果有相同,输出最左边的,如果还有相同,输出最低的那个点 分析: 线段树套平衡树. 我们先离散 ...

随机推荐

  1. Linux工作管理

    工作管理? 其实也就是把程序放到后台来管理,在windows中也就是最小化,在Linux中是通过命令把程序放到后台中.jobs命令查看后台程序. 对于第一点注意事项,mysql启动是例外的,要是叉掉了 ...

  2. Hands on Machine Learning with sklearn and TensorFlow —— 一个完整的机器学习项目(加州房地产)

    数据集地址:https://github.com/ageron/handson-ml/tree/master/datasets 先行知识准备:NumPy,Pandas,Matplotlib的模块使用 ...

  3. 亚马逊中国耳机巨头Jabra官方旗舰店上线

    日前,亚马逊中国(Z.cn)宣布,全球无线技术顶级领导品牌 Jabra (捷波朗)官方旗舰店正式上线,产品品类涵盖蓝牙耳机.音乐耳机.无线音箱和车载系列产品.Jabra 旗舰店上线伊始便汇集了 60 ...

  4. Sublime Text 2 - Unable to find git.exe 错误

    今日打开 Sublime Text 2,随即弹出 Package Control - Unable to find git.exe 错误.如下, 原因:曾经通过 git clone 命令获取过 Sub ...

  5. python基础知识-01-编码输入输出变量

    python其他知识目录 名词解释: 编辑器 ide 程序员 操作系统 ASCAII码 unicode utf-8 浅谈CPU.内存.硬盘之间的关系 操作系统及Python解释器工作原理讲解 关于编译 ...

  6. ERROR [IM002] [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序

    在用c#生成应用程序的时候,读写dbf时,open方法出错 ERROR [IM002] [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序 以前这个程序是用着好 ...

  7. java-HttpGetPost-图片字节流上传

    在java程序开发中经常用到与服务端的交互工作,主要的就是传递相应的参数请求从而获取到对应的结果加以处理 可以使用Get请求与Post请求,注意!这里的Get请求不是通过浏览器界面而是在程序代码中设置 ...

  8. ES6的新特性(7)——函数的扩展

    函数的扩展 函数参数的默认值 基本用法 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console ...

  9. 带你玩转JavaScript中的隐式强制类型转换

    正题开始前我想先抛出一个问题,==和===有什么区别?可能一般人会想,不就是后者除了比较值相等之外还会比较类型是否相等嘛,有什么好问的,谁不知道?!但是这样说还不够准确,两者的真正区别其实是==在比较 ...

  10. Linux 安装php扩展 swoole

    swoole是一个PHP的异步.并行.高性能网络通信引擎,使用纯C语言编写,提供了PHP语言的异步多线程服务器,异步TCP/UDP网络客户端,异步MySQL,异步Redis,数据库连接池,AsyncT ...