关闭

归并树 划分树 模板

169人阅读 评论(0) 收藏 举报
分类:

归并树

#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")

using namespace std;

const int MAX = 100010;
class Merger_tree{
public :
	class Tnode{
	public :
	    int l,r;
	    int len() { return r - l;}
	    int mid() { return MID(l,r);}
	    bool in(int ll,int rr) { return l >= ll && r <= rr; }
	    void lr(int ll,int rr){ l = ll; r = rr;}
	};
 	Tnode node[MAX<<2];
 	int seg[20][MAX],a[MAX],n;
	void init()
	{
		memset(seg,0,sizeof(seg));
		memset(node,0,sizeof(node));
	}
	void build(int s,int t){ n = t; Merger_build(1,s,t,1); }
	int find(int x,int y,int k) { return find_rank(n,x,y,k); };
	void Merger_build(int t,int l,int r,int deep)
	{
		node[t].lr(l, r);
		if( node[t].len() == 0 )
		{
			seg[deep][l] = a[l];
			return ;
		}
		int mid = MID(l, r);
		Merger_build(L(t), l, mid, deep+1);
		Merger_build(R(t), mid+1, r, deep+1);
		int k = l,i = l,j = mid+1;
		while( i <= mid && j <= r )
			if( seg[deep+1][i] < seg[deep+1][j] )
				seg[deep][k++] = seg[deep+1][i++];
			else
				seg[deep][k++] = seg[deep+1][j++];
		while( i <= mid )
			seg[deep][k++] = seg[deep+1][i++];
		
		while( j <= r )
			seg[deep][k++] = seg[deep+1][j++];
			
	}
	int find_k(int t,int l,int r,int deep,int val)
	{
		if( node[t].in(l,r) )
		{
			int ll = node[t].l, rr = node[t].r;
			while( ll < rr )
			{
				int mid = MID(ll, rr);
				if( seg[deep][mid] < val )
					ll = mid + 1;
				else
					rr = mid;
			}
			if( seg[deep][ll] <= val )
				return ll - node[t].l + 1;
			else
				return ll - node[t].l;
		}
		if( node[t].len() == 0 ) return 0;
		int ans = 0;
		int mid = node[t].mid();
		if( l <= mid ) ans += find_k(L(t), l, r, deep+1, val);
		if( r >= mid ) ans += find_k(R(t), l, r, deep+1, val);
		return ans;
	}		
	int find_rank(int n,int x,int y,int k)
	{
		int l = 1,r = n;
		while( l < r )
		{
			int mid = MID(l, r);
			if( find_k(1, x, y, 1, seg[1][mid]) < k )
				l = mid + 1;
			else
				r = mid;
		}
		return seg[1][l];
	}
};

Merger_tree t; 
int main()
{
	int n,m,x,y,k;
	while( ~scanf("%d%d",&n,&m) )
	{
		t.init();
		for(int i=1; i<=n; i++)
			scanf("%d",&t.a[i]);
		
		t.build(1,n);
		while( m-- )
		{
			scanf("%d%d%d",&x,&y,&k);
			int ans = t.find(x,y,k);
			printf("%d\n",ans);
		}
	}

return 0;
}

划分树

#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")

using namespace std;

const int MAX = 100010;
class Parti_tree{
public : 
	class Tnode{
	public :
	    int l,r;
	    int len() { return r - l;}
	    int mid() { return MID(l,r);}
	    bool in(int ll,int rr) { return l >= ll && r <= rr; }
	    void lr(int ll,int rr){ l = ll; r = rr;}
	};
	Tnode node[MAX<<2];
	int Left[20][MAX], seg[20][MAX], sa[MAX];
	void init()
	{
		memset(Left,0,sizeof(Left));
		memset(node,0,sizeof(node));
	}
	void build(int s,int t){ sort(sa+1,sa+t+1); Parti_build(1,s,t,1); }
    int find(int s,int t,int k){ return find_rank(1,s,t,1,k); }
	void Parti_build(int t,int l,int r,int d)
	{
		node[t].lr(l, r);
		if( node[t].len() == 0 ) return ;
		int mid = MID(l, r), lsame = mid - l + 1;
		for(int i=l; i<=r; i++)
			if( seg[d][i] < sa[mid] )
				lsame--;
		int lpos = l,rpos = mid+1,same = 0;
		for(int i=l; i<=r; i++)
		{
			if( i == l )
				Left[d][i] = 0;
			else
				Left[d][i] = Left[d][i-1];
			if( seg[d][i] < sa[mid] )
			{
				Left[d][i]++;
				seg[d+1][lpos++] = seg[d][i];
			}
			if( seg[d][i] > sa[mid] )
				seg[d+1][rpos++] = seg[d][i];
			if( seg[d][i] == sa[mid] )
				if( same < lsame )	
				{
					same++;
					Left[d][i]++;
					seg[d+1][lpos++] = seg[d][i];
				}
				else
					seg[d+1][rpos++] = seg[d][i];
		}
		Parti_build(L(t), l, mid, d+1);
		Parti_build(R(t), mid+1, r, d+1);		
	}
	int find_rank(int t,int l,int r,int d,int val)
	{
		if( node[t].len() == 0 )
			return seg[d][l];
		int s,ss;
		if( l == node[t].l )
		{
			s = Left[d][r];
			ss = 0;
		}
		else
		{
			s = Left[d][r] - Left[d][l-1];
			ss = Left[d][l-1];
		}
		if( s >= val )
			return find_rank(L(t), node[t].l+ss, node[t].l+ss+s-1, d+1, val);
		else
		{
			int mid = node[t].mid();
			int bb = l - node[t].l - ss;
			int b = r - l + 1 - s;
			return find_rank(R(t), mid+bb+1, mid+bb+b,d+1,val-s);
		}
	}
};

Parti_tree t;
int main()
{
	int n,m,x,y,k;
	
	while( ~scanf("%d%d",&n,&m) )
	{
		t.init();
		for(int i=1; i<=n; i++)
		{
			scanf("%d",&t.sa[i]);
			t.seg[1][i] = t.sa[i];
		}
		t.build(1,n);
		while( m-- )
		{
			scanf("%d%d%d",&x,&y,&k);
			int ans = t.find(x, y, k);
			printf("%d\n",ans);
		}
	}

return 0;
}



0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

归并树与划分树

归并树与划分树   2010-08-16 23:24:40|  分类: ACM|字号 订阅 据说最近挺热门的,想起寒假学过归并树,结果现在什么都不记得了,模拟了下归...
  • pi9nc
  • pi9nc
  • 2013-06-03 10:35
  • 1590

归并树&划分树详解

先放一张图片 对4 5 2 8 7 6 1 3 分别建划分树和归并树 划分树如下图 红色的点是此节点中被划分到左子树的点。       我们一般用一个结构体数组来保存每个节点,和线段树不同的是,线...
  • xindoo
  • xindoo
  • 2013-04-16 21:24
  • 2692

划分树算法 模板

转:http://www.cnblogs.com/pony1993/archive/2012/07/17/2594544.html划分树是一种基于线段树的数据结构。主要用于快速求出(在log(n)的时...
  • Littlewhite520
  • Littlewhite520
  • 2017-04-20 00:22
  • 284

生成最优归并树

算法连载(3)--生成最优归并树 分类: 开发/管理2005-04-13 22:10 1046人阅读 评论(0) 收藏 举报 算法treestructclassjoin 1....
  • pi9nc
  • pi9nc
  • 2013-09-12 13:29
  • 2531

败者树 多路归并排序

一 外部排序的基本思路 假设有一个72KB的文件,其中存储了18K个整数,磁盘中物理块的大小为4KB,将文件分成18组,每组刚好4KB。 首先通过18次内部排序,把18组数据排好序,得到初始的18...
  • xiaolei1982
  • xiaolei1982
  • 2016-02-23 11:35
  • 781

多路归并使用败者树的性能分析

编程珠玑第一个case是有关一个技巧性解决外部排序问题的。问题很巧妙的解决了,但一开始提到的利用归并排序进行外部排序的算法仍值得仔细探究一下,毕竟本科时学的不是很深入。 先来看内部排序中最简单的...
  • xiongbixb2
  • xiongbixb2
  • 2015-06-27 21:16
  • 642

k路归并(败者树,记录败者)

k路归并(败者树,记录败者) 分类: algorithm2013-09-15 16:33 102人阅读 评论(0) 收藏 举报 多路归并外排序败者树       败者树在外排...
  • pi9nc
  • pi9nc
  • 2013-09-15 21:51
  • 4518

胜者树 败者树 K-路最佳归并树 高效外部排序

外部排序 外部排序和内部排序还是有非常的的不同的,我们的外部排序主要针对的优化目标也是不同的,这里我先从外部排序的物理基础开始进行讲解 1.外存: 外部存储设备,相对于我们的内部存储设备而言具有一...
  • ltyqljhwcm
  • ltyqljhwcm
  • 2016-12-02 16:33
  • 2448

7.7.5 最佳归并树

文件经过置换-选择排序之后,得到的是长度不等的初始归并段。下面讨论如何组织初始归并段的归并顺序,使I/O访问次数最少。 m-路归并排序可用一棵m叉树描述,因为每一次作m路归并都需要m个归并段参加,因...
  • jxq0816
  • jxq0816
  • 2016-09-12 14:45
  • 3222

hdu1394(暴力/线段树/归并排序求逆序对的个数)

题目链接:Minimum Inversion Number 题目大意
  • pmt123456
  • pmt123456
  • 2017-02-18 00:08
  • 352
    个人资料
    • 访问:140174次
    • 积分:3116
    • 等级:
    • 排名:第12866名
    • 原创:192篇
    • 转载:18篇
    • 译文:0篇
    • 评论:15条
    最新评论