日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

poj 2201(RMQ+笛卡尔树)

發布時間:2025/3/16 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 poj 2201(RMQ+笛卡尔树) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

給出一些結點

每個節點有兩個關鍵字

要求構造一棵樹

第一個關鍵字滿足二叉搜索樹的性質,第二個關鍵字滿足小堆的性質


解題思路:這道題我開始是用第二關鍵字從小到大排序,然后從1-n去添加節點。這樣是符合最小堆的性質,假設添加第i個節點,那么首先去找[1,i-1]這段區間的第一關鍵字的最小值和最大值,如果i節點的第一關鍵字大于最大值,就直接添加到最大值節點的右兒子,如果小于最小值,就添加到最小值節點的左兒子,否則就直接從根節點往下找。可是超時了,其實超時的原因還蠻明顯的,因為你添加的i節點不一定每次都是大于最大值,小于最小值,更多的情況可能是在中間值,這樣每次都要從根節點出發往下走,這樣就會造成遍歷的時間太多了。但按照這種思路,很難直接找到i節點的父節點是誰,因為[1,i-1]區間內的第一關鍵字是無序的。

參考了網上的思路,絕大部分都是按照第一關鍵字排序,然后再去找區間段內的最小值作為子樹的根節點。

http://blog.csdn.net/sdj222555/article/details/7909198


我的TLE:

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std;const int maxn = 50005; struct Node {int k,a;int id;bool operator < (const Node &T){return a < T.a;} }tree[maxn]; struct Result {int parent,left,right; }res[maxn]; int n,value[maxn],dp_max[maxn][20],dp_min[maxn][20];int _max(int l,int r) {if(tree[l].k > tree[r].k) return l;return r; }int _min(int l,int r) {if(tree[l].k < tree[r].k) return l;return r; }void initRMQ() {for(int i = 1; i <= n; i++)dp_max[i][0] = dp_min[i][0] = i;for(int j = 1; (1 << j) <= n; j++)for(int i = 1; i + (1 << j) - 1 <= n; i++){dp_max[i][j] = _max(dp_max[i][j-1],dp_max[i+(1<<j-1)][j-1]);dp_min[i][j] = _min(dp_min[i][j-1],dp_min[i+(1<<j-1)][j-1]);} }int MaxValue(int l,int r) {int k = (int)(log((r - l + 1)*1.0) / log(2.0));return _max(dp_max[l][k],dp_max[r-(1<<k)+1][k]); }int MinValue(int l,int r) {int k = (int)(log((r - l + 1)*1.0) / log(2.0));return _min(dp_min[l][k],dp_min[r-(1<<k)+1][k]); }void Build() {int maxm,minm;for(int i = 1; i <= n; i++)res[i].parent = res[i].left = res[i].right = 0;for(int i = 2; i <= n; i++){maxm = MaxValue(1,i-1);minm = MinValue(1,i-1);if(tree[i].k > tree[maxm].k){res[tree[maxm].id].right = tree[i].id;res[tree[i].id].parent = tree[maxm].id;}else if(tree[i].k < tree[minm].k){res[tree[minm].id].left = tree[i].id;res[tree[i].id].parent = tree[minm].id;}else{int p = tree[1].id;while(true){if(tree[i].k > value[p]){if(res[p].right != 0)p = res[p].right;else{res[p].right = tree[i].id;res[tree[i].id].parent = p;break;}}else{if(res[p].left != 0)p = res[p].left;else{res[p].left = tree[i].id;res[tree[i].id].parent = p;break;}}}}} }int main() {while(scanf("%d",&n)!=EOF){for(int i = 1; i <= n; i++){scanf("%d%d",&tree[i].k,&tree[i].a);tree[i].id = i;value[i] = tree[i].k;}sort(tree+1,tree+1+n);initRMQ();Build();printf("YES\n");for(int i = 1; i <= n; i++)printf("%d %d %d\n",res[i].parent,res[i].left,res[i].right);}return 0; }

總結

以上是生活随笔為你收集整理的poj 2201(RMQ+笛卡尔树)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。