• SGU 155.Cartesian Tree


    时间限制:0.25s

    空间限制:6M

    题意:

          给出n(n< 50000)个含双关键字(key,val)的节点,构造一颗树使该树,按key值是一颗二分查找树,按val值是一个小根堆.


    Solution :

                 先按k值从小到大排序.

                 再从序列中找到最小的val值,将其作为根.再对它的左边和右边做同样的操作.左边最大的数做左儿子,右边做右儿子。递归即可.

                 这里要快速找到一个序列区间的最大值,用ST方法求RMQ就行了.

                 时间复杂度O(nlogN),空间复杂度O(n)

    code:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <functional>
    #include <vector>
    #include <utility>
    using namespace std;
    
    struct node {
    	int key, val, ID;
    } p;
    
    struct answer {
    	int fa, lson, rson;
    } ans[51000];
    
    typedef pair<int , int > P;
    vector<node> f;
    P st[51000][20];
    int n, x, y;
    
    bool cmp (node a, node b) {
    	return a.key < b.key;
    }
    //ST RMQ
    void ST() {
    	for (int i = n - 1; i >= 0 ; i--)
    		for (int j = 1; i + (1 << j) <= n; j++)
                  {
    			if (st[i][j - 1].first < st[i + (1 << j - 1)][j - 1].first)
    				st[i][j] = st[i][j - 1];
    			else
    				st[i][j] = st[i + (1 << j - 1)][j - 1];
    		}
    }
    //得到区间最小值的位置
    int getmin (int l, int r)
    {
    	P tem;
    	tem=st[l][0];
    	for (int k = 0; l + (1 << k) <= r; k++)
           {
    		if (st[l][k].first < tem.first)
    			tem = st[l][k];
    		if (st[r - (1 << k) + 1][k].first < tem.first)
    			tem = st[r - (1 << k) + 1][k];
    	}
    	return tem.second;
    }
    //递归建树
    int make (int l, int r, int fa)
    {
    	int k = getmin (l, r);
    	int pos = f[k].ID;
    	ans[pos].fa = fa;
    	if (l >= r) return pos;
    	if (l < k) ans[pos].lson = make (l, k - 1, pos);
    	if (k < r) ans[pos].rson = make (k + 1, r, pos);
    	return pos;
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for (int i = 0; i < n; i++)
    	{
    		scanf("%d %d",&x,&y);
    		p.key = x, p.val = y, p.ID = i + 1;
    		f.push_back (p);
    	}
    	//按key值从小到大排序
    	sort (f.begin(), f.end(), cmp);
    	for (int i = 0; i < (int) f.size(); i++)
    		st[i][0] = make_pair (f[i].val, i);
    	ST();
    	make (0, n - 1, 0);
    	//一定有解直接输出 "YES"
    	puts("YES
    ");
    	for (int i = 1; i <= n; i++)
                  printf("%d %d %d
    ",ans[i].fa,ans[i].lson,ans[i].rson);
    	return 0;
    }
    

      

      

  • 相关阅读:
    MVC+jQuery开发B/S系统②:表单绑定
    插入排序
    笔记:实例管理
    文件读写冲突的解决办法:ReaderWriterLock
    MVC+jQuery数据绑定①:列表绑定(二)
    MVC+jQuery数据绑定①:列表绑定(三)
    非递归求 T(n) = [T(n1),n,T(n1)] 已知T1=[1]
    笔记:契约总结
    面试题:1~ n1 有n个数,是有序的,找出重复的那个数。
    Thread系列——ThreadPool
  • 原文地址:https://www.cnblogs.com/keam37/p/3864681.html
Copyright © 2020-2023  润新知