Codeforces 19D Points 线段树+set

题目链接:点击打开链接

线段树维护y值大于val的最小x值

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>
#include <map>
#include <set>
#include <math.h>
using namespace std;
#define inf 1000000010
#define ll int
#define N 200005
#define L(x) (x<<1)
#define R(x) (x<<1|1)
inline ll Mid(ll a,ll b){return (a+b)>>1;}
ll n;
struct node{
	ll x,y;
	node(ll a=0,ll b=0):x(a),y(b){}
	bool operator<(const node &a) const{
		if(a.x==x)
			return a.y>y;
		return a.x>x;
	}
	ll op;
}in[N];
set<node>myset;
set<node>::iterator p;
struct Edge{
	int l, r, id;
	int maxx, lval;
	set<ll>st;
}tree[N<<4];
set<ll>::iterator pp;
set<ll>lisan;
void build(int l,int r,int id){
	tree[id].l =l ,tree[id].r =r;
	tree[id].maxx = tree[id].lval = -1;
	tree[id].st.clear();
	tree[id].st.insert(-1);
	if(l==r)return ;
	int mid = Mid(l,r);
	build(l,mid,L(id));
	build(mid+1,r,R(id));
}
void updata(ll pos, ll id, ll val, ll o){ // o = 1表示插入
	if(tree[id].l== tree[id].r) {
		if(o==1){
			tree[id].st.insert(val);
			tree[id].lval = tree[id].maxx = max(tree[id].maxx,val);
			return ;
		}
		else tree[id].st.erase(val);
		pp = tree[id].st.end(); pp--;
		tree[id].lval = tree[id].maxx = *pp;
		return;
	}
	ll mid = Mid(tree[id].l,tree[id].r);
	if(mid<pos)updata(pos,R(id),val,o);
	else updata(pos, L(id),val,o);
	tree[id].lval = tree[L(id)].lval;
	tree[id].maxx = max(tree[L(id)].maxx, tree[R(id)].maxx);
}
ll query(ll l, ll r, ll id, ll val){
	if(l <=tree[id].l && tree[id].r<=r) {
		if(tree[id].maxx <= val)return -1;
		if(tree[id].lval >val)return tree[id].l;
	}
	ll mid = Mid(tree[id].l,tree[id].r);
	if(mid<l)return query(l,r,R(id),val);
	else if(r<=mid)return query(l,r,L(id),val);
	ll ans = query(l,mid,L(id),val);
	if(ans!=-1)return ans;
	return query(mid+1,r,R(id),val);
}
ll pos[N<<1];
map<ll,ll>mp;
int main(){
	ll x,y;
	while(~scanf("%d",&n)) {
		myset.clear();
		mp.clear();
		lisan.clear();
		for(ll i = 0; i < n; i++) {
			char s[10];scanf("%s",s);
			scanf("%d %d",&in[i].x,&in[i].y);
			lisan.insert(in[i].x);
			if(s[0]=='a')in[i].op = 1;
			else if(s[0]=='r')in[i].op=2;
			else in[i].op = 3;
		}
		ll siz = 1;
		for(pp=lisan.begin(); pp!=lisan.end(); pp++) {
			pos[siz] = *pp;
			mp.insert(pair<ll,ll>(*pp,siz));
			siz++;
		}
		for(ll i = 0; i < n; i++)in[i].x = mp.find(in[i].x)->second;
		build(1,siz,1);
		for(ll i = 0; i < n; i++){
			x = in[i].x, y = in[i].y;
			if(in[i].op == 1){
				myset.insert(node(pos[x],y));
				updata(in[i].x,1,in[i].y,1);
			}
			else if(in[i].op == 2){
				myset.erase(node(pos[x],y));
				updata(in[i].x,1,in[i].y,0);
			}
			else {
				ll he = query(in[i].x+1,siz,1,in[i].y);
				if(he==-1){puts("-1");continue;}
				printf("%d %d\n",pos[he],myset.lower_bound(node(pos[he],in[i].y+1))->y);
			}
		}
	}
	return 0;
}

Codeforces 19D Points 线段树+set,布布扣,bubuko.com

时间: 2024-08-08 05:32:47

Codeforces 19D Points 线段树+set的相关文章

Codeforces 19D Points(树状数组)

题目链接:Codeforces 19D Points 题目大意:N中操作,每次添加一个点,或者删除一个点,以及找到给定x,y坐标最近的一个坐标,并且保证xi,yi在x,y的右上角. 解题思路:这题的解法还是很机智的. y坐标离散化,然后树状数组的每个单位用一个set代替,set记录的是点集. 剩下的操作就像树状数组一样,每次添加就等于是+w的操作,移除就等于是-w,只是w是一个点,那么find操作就等于是在sum操作生成的点集中二分查找. #include <cstdio> #include

CodeForces 46DParking Lot线段树

#include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include <list> #include <set> #include <qu

Codeforces 444C(线段树)

区间颜色不一致就更新到底,否则lazy标记 #include<cstdio> #include<cstring> #include<cmath> #include<queue> using namespace std; #define lc l,m,index<<1 #define rc m+1,r,index<<1|1 #define N 100005 #define ll __int64 struct node { bool sa

CodeForces 19D Points(线段树+map)

开始想不通,后来看网上说是set,就有一个想法是对每个x建一个set...然后又想直接建立两重的set就好,最后发现不行,自己想多了...  题意是给你三种操作:add (x y) 平面添加(x y)这个点 remove (x y)平面删除(x y)这个点 find (x y) 查找(x y)这个点严格的右上方中最左边的点,有多个就再找最下方的点,输出 其实想通了还是比较简单的,我的想法就是对于x先排序再对y排序,这样建一颗线段树,用处在于:添加和删除都可以当成单点更新,只需要记录最大值就好.f

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

Extending Set of Points 我们能发现, 如果把x轴y轴看成点, 那么答案就是在各个连通块里面的x轴的个数乘以y轴的个数之和. 然后就变成了一个并查集的问题, 但是这个题目里面有撤销的操作, 所以我们要把加入和撤销操作变成 这个点影响(L , R)之间的询问, 然后把它丢到线段树里面分成log段, 然后我们dfs一遍线段树, 用按秩合并并查集取维护, 回溯的时候将并查集撤销. #include<bits/stdc++.h> #define LL long long #def

New Year and Old Subsequence CodeForces - 750E(线段树 + 矩阵)

New Year and Old Subsequence (CodeForces - 750E) 题意: 给出一个长度为\(N\)的数字串,\(q\)次询问.每次询问一段区间.在区间内删除尽量少的字符,使得区间内含有序列"\(2017\)",且不含有"\(2016\)". \(n,q<=200000\). 题解: 用\(01234\)五种状态分别表示"". "\(2\)"."\(20\)"."

Sum Queries? CodeForces - 1217E (线段树)

Sum Queries? CodeForces - 1217E (线段树) 题意: 定义一个集合为\(balanced\)的,当且仅当集合内数字之和的每个十进制位,都与集合中某个数该位相同.否则,称该集合为\(unbalanced\)的. 给定一个长度为\(n\)的序列,\(q\)次询问一个区间内数字之和最小的\(unbalanced\)集合,输出数字之和.若没有输出\(-1\). \(n,q<=200000\). 题解: 可以发现,如果存在\(unbalanced\)集合,那么最小的一定是只两

CodeForces 383C-dfs序-线段树

题意:一棵根为1的多叉树有n个点,题目有m次询问.第一行输入n和m,第二行输入n-1条边, 以后m行输入操作,操作有两种:1 x val 表示 节点的值x+val,同时它的儿子层节点的值-val,孙子层节点的值+val...如此往下直到叶子节点:2 x 表示输出x节点的当前值. 思路:类似poj3321,用dfs序重新表示每个节点,这样更新子树的操作就变成更新区间了,区间是:[i, i+cnt][当前节点的dfs序为 i, 儿子数为cnt],查询同理,单点查询当前节点的dfs序.但是这道题的df

【题解】Berland.Taxi Codeforces 883L 模拟 线段树 堆

Prelude 题目传送门:ヾ(?ω?`)o Solution 按照题意模拟即可. 维护一个优先队列,里面装的是正在运营中的出租车,关键字是乘客的下车时间. 维护一个线段树,第\(i\)个位置表示第\(i\)个房子前面有没有停放出租车,这样在有人需要打车的时候可以快速找到离她最近的车的位置. 对每个房子维护一个堆,里面装的是停在这个房子前面的出租车,关键字是出租车的编号和上一个乘客下车的时间,上一个乘客下车越早,等待时间越长. 然后模拟时间的流逝就可以了,代码非常好写. Code #includ