zoukankan      html  css  js  c++  java
  • poj_2352 Treap

    题目大意

        对于二维平面上的n个点,给出点的坐标。定义一个点A覆盖的点的个数为满足以下条件的点B的个数:点B的x <= 点A的x坐标,点B的y坐标 <= 点A的y坐标。 
        给出N个点的坐标,求出覆盖点的个数分别为0, 1, ... N-1 的点各有多少个。

    题目分析

        对于二维平面的点问题,可以考虑先进行行列排序,然后进行处理。对点进行排序(y从小到大,y相同,x从小到大)之后,按照y从小到大进行:单独考虑一行的点的x坐标,此时x坐标是升序的,因此当前点的肯定可以覆盖当前行中的之前访问的点;对于下方的点,它们的y坐标肯定小于当前点的y坐标,因此只考虑点的x坐标,如果x坐标小于等于当前点的x坐标,则点被当前点覆盖。 
        于是问题就化为了,按照从左下到右上的顺序遍历每个点的时候,比较该点和之前访问过的点的x坐标,统计之前点中x坐标小于等于当前点x坐标的个数 
        这就成了一个查找问题,查找问题可以考虑使用二查找树,于是可以使用treap这种平衡树。

    实现(c++)

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    #define MAX_NODE_NUM 15500
    struct TreapNode{
    	int key;
    	int priority;
    	int size;
    	int count;
    	TreapNode* child[2];
    	TreapNode(int val){
    		key = val;
    		child[0] = child[1] = NULL;
    		size = count = 1;
    		priority = rand();
    	}
    	void Update(){
    		size = count;
    		if (child[0]){
    			size += child[0]->size;
    		}
    		if (child[1]){
    			size += child[1]->size;
    		}
    	}
    };
    
    struct Treap{
    	TreapNode* root;
    	Treap() :root(NULL){};
    	
    	void Rotate(TreapNode*& node, int dir){
    		TreapNode* ch = node->child[dir];
    		node->child[dir] = ch->child[!dir];
    		ch->child[!dir] = node;
    
    		node->Update();	//这时候node已经旋转到下方一层,因此size可能发生变化
    
    		node = ch;
    	}
    	
    	void Insert(TreapNode*& node, int key){
    		if (!node){
    			node = new TreapNode(key);
    		}
    		else if (node->key == key){
    			node->count++;
    		}
    		else {
    			int dir = node->key < key;
    			Insert(node->child[dir], key);
    			if (node->priority < node->child[dir]->priority){
    				Rotate(node, dir);
    			}
    		}
    		node->Update();
    	}
    	void debug(TreapNode* node){
    		if (node){
    			debug(node->child[0]);
    			printf("node's key = %d, priority = %d, count = %d, size = %d
    ", node->key, node->priority, node->count, node->size);
    			debug(node->child[1]);
    		}
    	}
    	
    	int GetLessK(TreapNode* node, int k){
    		int sum = 0;
    		if (!node){
    			return 0;
    		}
    		if (node->key > k){
    			sum += GetLessK(node->child[0], k);
    		}
    		else{
    			sum += node->count;
    			if (node->child[0]){
    				sum += node->child[0]->size;
    			}
    			sum += GetLessK(node->child[1], k);
    		}
    		return sum;
    	}
    };
    
    struct Point{
    	int x;
    	int y;
    };
    
    Point gPoints[MAX_NODE_NUM];
    
    Treap gTreap;
    int gCoverNum[MAX_NODE_NUM];
    int main(){
    
    	int N;
    	scanf("%d", &N);
    	for (int i = 0; i < N; i++){
    		scanf("%d %d", &gPoints[i].x, &gPoints[i].y);
    		gCoverNum[i] = 0;
    	}
    	for (int i = 0; i < N; i++){
    		int less_count = gTreap.GetLessK(gTreap.root, gPoints[i].x);
    		gCoverNum[less_count] ++;
    
    		gTreap.Insert(gTreap.root, gPoints[i].x);
    
    	/*rintf("##################
    ");
    		gTreap.debug(gTreap.root);
    		printf("##################
    ");
    		*/
    
    	}
    	for (int i = 0; i < N; i++){
    		printf("%d
    ", gCoverNum[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    source vimrc的时候报错:.vimrc:1: command not found: syntax
    python Qt5 实战(一)按钮颜色
    python做中学(二)bool()函数的用法
    python做中学(一)全局变量的用法
    音频算法speex中的aec分析以及解析
    ubuntu 18.04 安装mysql 遇到语言格式不兼容性问题解决
    ubuntu18.04 中个性化配置vim方法
    蓝牙协议栈中关于回连和断开的定义
    autojump--懒人利器
    终端中的 zsh 和 bash-魔法切换
  • 原文地址:https://www.cnblogs.com/gtarcoder/p/4715457.html
Copyright © 2011-2022 走看看