POJ 2201 RMQ 笛卡尔树

来源:互联网 发布:远程控制软件排行 编辑:程序博客网 时间:2024/05/16 11:20

给出一些结点

每个节点有两个关键字

要求构造一棵树

第一个关键字满足二叉搜索树的性质,第二个关键字满足小堆的性质

和1785几乎一模一样

题目还让输出yes 或者no  实际上,因为所有的第一关键字互异,第二关键字也互异,所以一定能构造出来这样的树

这题不用treap的原因我嫌treap有点麻烦,还旋转啥的,没RMQ直观好想

#include <iostream>#include <algorithm>#include <cstring>#include <string>#include <cstdio>#include <cmath>#include <queue>#include <map>#include <set>#define eps 1e-5#define MAXN 55555#define MAXM 5555#define INF 100000007using namespace std;int n;struct node{    int x, w, id;}p[MAXN];bool cmp(node x, node y){    return x.x < y.x;}int mi[MAXN][17], mx[MAXN][17];void rmqinit(){    for(int i = 1; i <= n; i++) mi[i][0] = mx[i][0] = i;    int m = (int)(log(n * 1.0) / log(2.0));    for(int i = 1; i <= m; i++)        for(int j = 1; j <= n; j++)        {            mx[j][i] = mx[j][i - 1];            mi[j][i] = mi[j][i - 1];            int k = j + (1 << (i - 1));            if(k <= n)            {                if(p[mx[j][i]].w < p[mx[k][i - 1]].w) mx[j][i] = mx[k][i - 1];                if(p[mi[j][i]].w > p[mi[k][i - 1]].w) mi[j][i] = mi[k][i - 1];            }        }}int rmqmin(int l,int r){    int m = (int)(log((r - l + 1) * 1.0) / log(2.0));    if(p[mi[l][m]].w > p[mi[r - (1 << m) + 1][m]].w) return mi[r - (1 << m) + 1][m];    else return mi[l][m];}int ans[MAXN][3];int solve(int fa, int s, int t){    if(s > t) return 0;    int pos = rmqmin(s, t);    int id = p[pos].id;    ans[id][0] = fa;    ans[id][1] = solve(id, s, pos - 1);    ans[id][2] = solve(id, pos + 1, t);    return id;}int main(){    while(scanf("%d", &n) != EOF)    {        for(int i = 1; i <= n; i++) scanf("%d%d", &p[i].x, &p[i].w), p[i].id = i;        sort(p + 1, p + n + 1, cmp);        rmqinit();        solve(0, 1, n);        puts("YES");        for(int i = 1; i <= n; i++) printf("%d %d %d\n", ans[i][0], ans[i][1], ans[i][2]);    }    return 0;}


原创粉丝点击