SGU155(笛卡尔树的构造)
生活随笔
收集整理的這篇文章主要介紹了
SGU155(笛卡尔树的构造)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
題目:http://acm.sgu.ru/problem.php?contest=0&problem=155
?
題意:給出每個點的兩個值key和fix,且所有的key值和fix值都是不相同的,要求構造出笛卡爾樹。輸入每個點的兩個權
值,輸出笛卡爾樹每個結點(按照輸入的順序編號)的父親結點和兩個兒子的編號。
?
分析:首先,笛卡爾樹對于key來說是二叉搜索樹,對于fix來說是最小堆,所以跟Treap一樣。笛卡爾樹在LCA和RMQ問題中有
著重要的應用。這題首先記錄下每個結點的ID,然后以key為關鍵字排序。排完了之后就會有線性的構造笛卡爾樹的算法了。
這里的笛卡爾樹一定是存在的,所以先輸出YES。
?
構造笛卡爾樹的過程:
使用數據結構棧,棧中保存的始終是右鏈,即根結點、根結點的右兒子、根結點的右兒子的右兒子……組成的鏈,并且棧中從
棧頂到棧底key依次減小。
如果按照從后到前的順序判斷一個元素是否大于a[i],則每次插入的時間復雜度為O(k+1),k為本次插入中移除的右鏈元素個
數。因為每個元素最多進出右鏈各一次,所以整個過程的時間復雜度為O(n)。
#include <iostream> #include <string.h> #include <algorithm> #include <stdio.h>using namespace std;const int N=1000005; const int INF=~0U>>1;struct node {int id; //id記錄節點的編號,從1開始int key,fix; //二元組int pre,l,r; //分別表示當前節點的父親,左兒子和右兒子void clear(){pre=l=r=0;}bool operator < (node t) const{return key<t.key;} };node T[N];int stack[N],p[N],top;void Init(int n) {for(int i=1; i<=n; i++)T[i].pre=T[i].l=T[i].r=0;T[0].fix=-INF; }int Build(int n) {top=0;stack[++top]=1;for(int i=2; i<=n; i++){while(top>=0&&T[i].fix<T[stack[top]].fix)--top;if(top){T[i].pre=stack[top];T[i].l=T[stack[top]].r;T[T[stack[top]].r].pre=i;T[stack[top]].r=i;stack[++top]=i;}else{T[stack[1]].pre=i;T[i].l=stack[1];stack[++top]=i;}}return stack[1]; }int main() {int n;scanf("%d",&n);Init(n);for(int i=1; i<=n; i++){scanf("%d%d",&T[i].key,&T[i].fix);T[i].id=i;}sort(T+1,T+n+1);int root=Build(n);for(int i=1; i<=n; i++)p[T[i].id]=i;puts("YES");for(int i=1; i<=n; i++)printf("%d %d %d\n",T[T[p[i]].pre].id,T[T[p[i]].l].id,T[T[p[i]].r].id);return 0; }總結
以上是生活随笔為你收集整理的SGU155(笛卡尔树的构造)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SPOJ3273(Treap)
- 下一篇: POJ1785(笛卡尔树的构造)