点击打开cf 19D
思路: 线段树+单点更新
分析:
1 题目的意思是给定一些点和n个操作,这些点都是在原点(0 , 0)的右边,现在给定三种操作
add x y 是把(x , y)这个点加入
remove x y 是把(x , y)这个点删除
find x y是查找(x , y)点的右边的点满足x' > x && y' > y 并且有x'和y‘尽量的小
2 题目给定的数据是n是2*10^5,但是点的最大值为10^9,所以我们应该要进行点的离散化。但是我们只要对x进行离散化即可
3 我们利用set来保存每一个x对应的y的集合,然后我们利用线段树来维护一个x区间的最大的y。
为什么要用线段树呢?因为我们知道我们只要只要当前区间的最大值就能够判断是否有没有存在这样的点,然后我们利用二分逼近的思想去求出这个x。只要我们求出了x,那么我们就可以利用之前的set来找比y大的y',这一步可以利用set的内置的lower_bound
4 有一点很重要的就是,由于set和map的存储结构不是线性的,因此它们内置了lower_bound和upper_bound,所以我们利用内置,如果使用通用的时间效率及其底下
代码:
/************************************************
* By: chenguolin *
* Date: 2013-09-08 *
* Address: http://blog.csdn.net/chenguolinblog *
************************************************/
#include<set>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Lson(x) (x<<1)
#define Rson(x) (Lson(x)|1)
#define Mid(x,y) ((x+y)>>1)
#define Sum(x,y) (x+y)
const int MAXN = 200010;
struct Edge{
int mark;
int x;
int y;
};
Edge e[MAXN];
struct Node{
int left;
int right;
int max_y;
};
Node node[4*MAXN];
int n , m;
int num[MAXN];
set<int>s[MAXN];
void input(){
m = 1;
char str[10];
for(int i = 1 ; i <= n ; i++){
scanf("%s%d%d" , str , &e[i].x , &e[i].y);
if(str[0] == 'a')
e[i].mark = 1;
else if(str[0] == 'r')
e[i].mark = 2;
else
e[i].mark = 3;
s[m].clear();
num[m++] = e[i].x;
}
}
inline void push_up(int pos){
node[pos].max_y = max(node[Lson(pos)].max_y , node[Rson(pos)].max_y);
}
void buildTree(int left , int right , int pos){
node[pos].left = left;
node[pos].right = right;
node[pos].max_y = -1;
if(left == right)
return;
int mid = Mid(left , right);
buildTree(left , mid , Lson(pos));
buildTree(mid+1 , right , Rson(pos));
}
void update(int x , int pos){
if(node[pos].left == node[pos].right){
if(s[x].size())
node[pos].max_y = *(--s[x].end());
else
node[pos].max_y = -1;
return;
}
int mid = Mid(node[pos].left , node[pos].right);
if(x <= mid)
update(x , Lson(pos));
else
update(x , Rson(pos));
push_up(pos);
}
int query(int x , int y , int pos){
if(node[pos].right <= x)
return -1;
if(node[pos].max_y <= y)
return -1;
if(node[pos].left == node[pos].right)
return node[pos].left;
int t = query(x , y , Lson(pos));
if(t == -1)
t = query(x , y , Rson(pos));
return t;
}
void solve(){
sort(num+1 , num+1+m);
m = unique(num+1 , num+1+m)-(num+1);
buildTree(1 , m , 1);
for(int i = 1 ; i <= n ; i++){
int x = upper_bound(num+1 , num+1+m , e[i].x)-(num+1);
int y = e[i].y;
// add
if(e[i].mark == 1){
s[x].insert(y);
update(x , 1);
}
// remove
else if(e[i].mark == 2){
s[x].erase(y);
update(x , 1);
}
// find
else{
int ans = query(x , y , 1);
if(ans == -1)
puts("-1");
else{
printf("%d %d\n" , num[ans] , *s[ans].upper_bound(y));
}
}
}
}
int main(){
while(scanf("%d%*c" , &n) != EOF){
input();
solve();
}
return 0;
}
分享到:
相关推荐
Codeforces 题库 101-200 共~500题 codeforces.com版权所有。 程序可提交至该网站评测。
codeforces编程网站预测分数插件
Codeforces 题库 001-100 共~500题 codeforces.com版权所有。 程序可提交至该网站评测。
使用于Google Chrome的Codeforces Enhancer 1.1.2插件安装包。 版本:codeforces enhancer 1.1.2 使用浏览器:Google Chrome
Codeforces 185A - Plant 全测试点49个
codeforces 19 E Fairy 一道比较难的题目的解题报告 推荐阅读
codeforces每日一题。 题意: 给出一个数组,让你挑选出能组成任意pair差值为2的幂的序列,并且使这个序列长度尽可能大。 思路: 针对于挑选出来的序列,任意pair对的差值为2的幂数。 假设有多个pair对,设dis(a,b)=2...
Codeforces global round 10 codes
Codeforces round 678 division 2 codes
Some of the Codeforces problems codes
一个Codeforces、牛客竞赛、AtCoder平台的编程竞赛查询插件,ACMer必备.zip
Codeforces round 678 D2_Codeforces_源码
# sublime-plugin-for-codeforces 自定义构建,用于从 codeforces 获取测试用例并检查程序是否正确。 平台:GNU/Linux 语言:Python2.7.9 描述:这个程序从 codeforces 中获取测试用例,并告诉你程序的输出是否与...
lucifer1004大佬的博客cf上分攻略故里大佬的githubcf思维题刷题数:44- (1421)codeforces 676 div2 A,B done
PDF-CodeForces问题 PDF文件中的CodeForces问题 利用CodeForces提取在这个库中的文件 ,文件夹名代表来自CodeForces网址contests`的ID,每个文件夹包含比赛的问题。 有关CodeForces竞赛的疯狂事实 CodeForces上有937...
codeforces-js Codeforces JS
打codeforces的神器
Codeforces Round #723 (Div. 2).md
codeforces-plugin-sublime-text 注意:仅适用于 C++ 代码。 它能做什么? 编译你的 C++ 代码,构建它,获取测试用例,在上面运行你的代码,比较输出。 它不做什么: 通过互联网神奇地识别您的问题并进行判断。 ...
来自2012,2013年国际信息奥林匹克金牌得主许昊然