POJ 2352 Stars Treap & 线段树

其实这里就是用Treap来实现了一个求和的过程,其实这种区间操作还是用线段树或者是Splay比较方便。

将点排序之后随便搞一下就就好,要注意的就是有点重复情况,我这里是把树的每一个节点又添加了一个cnt域来维护的,自己手撸的平衡树就是这么灵活= =

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>

using namespace std;

typedef long long LL;

struct Node {
	Node *ch[2];
	int rkey, size, val, cnt;
	Node(int val) : val(val) {
		ch[0] = ch[1] = NULL;
		rkey = rand();
		size = cnt = 1;
	}
	void maintain() {
		size = cnt;
		if (ch[0] != NULL) size += ch[0]->size;
		if (ch[1] != NULL) size += ch[1]->size;
	}
};

struct Treap {

	Node *root;

	Treap() {
		root = NULL;
	}

	void rotate(Node *&o, int d) {
		Node *k = o->ch[d ^ 1];
		o->ch[d ^ 1] = k->ch[d];
		k->ch[d] = o;
		k->maintain(); o->maintain();
		o = k;
	}

	void remove_tree(Node *&o) {
		if (o == NULL) return;
		if (o->ch[0] != NULL) remove_tree(o->ch[0]);
		if (o->ch[1] != NULL) remove_tree(o->ch[1]);
		delete o;
		o = NULL;
	}

	void insert(Node *&o, int x) {
		if (o == NULL) o = new Node(x);
		else if (o->val == x) o->cnt++;
		else {
			int d = x > o->val;
			insert(o->ch[d], x);
			if (o->ch[d]->rkey > o->rkey) rotate(o, d ^ 1);
		}
		o->maintain();
	}

	int getsize(Node *o) {
		if (o == NULL) return 0;
		return o->size;
	}

	int query(Node *o, int x) {
		if (o == NULL) return 0;
		if (o->val == x) {
			return getsize(o->ch[0]) + o->cnt - 1;
		}
		if (x > o->val) return getsize(o->ch[0]) + o->cnt + query(o->ch[1], x);
		else return query(o->ch[0], x);
	}

	void clear() {
		remove_tree(root);
	}

	void insert(int x) {
		insert(root, x);
	}

	int query(int x) {
		return query(root, x);
	}
};

const int maxn = 2e4 + 10;

struct Point {
	int x, y;
	Point(int x = 0, int y = 0) : x(x), y(y) {}
	bool operator < (const Point &p) const {
		if (y == p.y) return x < p.x;
		return y < p.y;
	}
};

int levcnt[maxn], n;
Point p[maxn];
Treap tree;

int main() {
	while (scanf("%d", &n) != EOF) {
		for (int i = 1; i <= n; i++) {
			int x, y; scanf("%d%d", &x, &y);
			p[i] = Point(x, y);
		}
		sort(p + 1, p + 1 + n);
		memset(levcnt, 0, sizeof(levcnt));
		tree.clear();
		for (int i = 1; i <= n; i++) {
			tree.insert(p[i].x);
			int ret = tree.query(p[i].x);
			levcnt[ret]++;
		}
		for (int i = 0; i < n; i++) {
			printf("%d\n", levcnt[i]);
		}
	}
	return 0;
}

  

时间: 2025-01-02 13:47:47

POJ 2352 Stars Treap & 线段树的相关文章

POJ 2352 Stars(线段树)

题目地址:POJ 2352 今天的周赛被虐了. . TAT..线段树太渣了..得好好补补了(尽管是从昨天才開始学的..不能算补...) 这题还是非常easy的..维护信息是每个横坐标的出现的次数. 代码例如以下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h>

!POJ 2352 左下角星星-线段树-(单点更新,区间查询)

题意:直接坐标系中有n个星星,每个星星左下角的星星个数是它的价值,输出价值为0~n-1的星星个数. 分析: 这题就没有上面四道线段树的题裸了. 这题是怎么联系到区间,然后用线段树维护的呢? 因为题目要求输入的次序是按y第一关键字,x第二关键字升序输入,那么我们可以想到对于星星A(x,y),它左下角的星星一定在比他先输入的星星中,所以我们只需判断在比他先输入的星星的x2,如果x2<=x,那么星星A的价值+1.所以这题就转化为了求区间中的tot[0~x],也就是区间查询.每输入一个星星,先在原来的树

hdu 1541/poj 2352:Stars(树状数组,经典题)

Stars Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4052    Accepted Submission(s): 1592 Problem Description Astronomers often examine star maps where stars are represented by points on a plan

POJ 2481 Cows &amp;&amp; POJ 2352 Stars(树状数组妙用)

题目链接:POJ 2481 Cows POJ 2352 Stars 发现这两个题目都跟求逆序数有着异曲同工之妙,通过向树状数组中插入点的位置,赋值为1,或者++,然后通过求和来判断比当前 点 "小" 的有多少点. Cows需要自己排序, Stars题目已经给排好序. POJ 2352 Stars 题目大意为在二维坐标上给出一些星星的坐标,求某一个星星左方,下方,左下方的星星个数.题目已经把星星按照Y坐标从小到大,X从小到大排序.因此,在每次对一个星星进行统计时,之前出现过的星星,只要X

poj 2352 Stars 数星星 详解

题目: poj 2352 Stars 数星星 题意:已知n个星星的坐标.每个星星都有一个等级,数值等于坐标系内纵坐标和横坐标皆不大于它的星星的个数.星星的坐标按照纵坐标从小到大的顺序给出,纵坐标相同时则按照横坐标从小到大输出. (0 <= x, y <= 32000) 要求输出等级0到n-1之间各等级的星星个数. 分析: 这道题不难想到n平方的算法,即从纵坐标最小的开始搜,每次找它前面横坐标的值比它小的点的个数,两个for循环搞定,但是会超时. 所以需要用一些数据结构去优化,主要是优化找 横坐

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

POJ训练计划1177_Picture(扫描线/线段树+离散)

解题报告 题意: 求矩形周长和. 思路: 左扫上扫,扫过了. #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; struct Seg { int lx,rx,ly,ry,h,v; friend bool operator < (Seg a,Seg b) { re

POJ训练计划2828_Buy Tickets(线段树/单点更新)

解题报告 题意: 插队完的顺序. 思路: 倒着处理数据,第i个人占据第j=pos[i]+1个的空位. 线段树维护区间空位信息. #include <iostream> #include <cstdio> #include <cstring> using namespace std; struct node { int x,v; } num[201000]; int sum[1000000],ans[201000]; void cbtree(int rt,int l,in

POJ 1151 Atlantis 扫描线+线段树

点击打开链接 Atlantis Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17252   Accepted: 6567 Description There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of pa