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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

SGU155(笛卡尔树的构造)

發布時間:2024/4/11 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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(笛卡尔树的构造)的全部內容,希望文章能夠幫你解決所遇到的問題。

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