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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

二维偏序 tree

發(fā)布時間:2025/3/15 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二维偏序 tree 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

tree(二維偏序)

最近接觸到一些偏序的東西。

傳統(tǒng)線段樹非葉子節(jié)點的劃分點mid=(l+r)/2,但小R線段樹mid是自己定的。但滿足l<=mid<r,其余條件同原來線段樹。那么不難發(fā)現(xiàn)如下性質:1.該線段樹的節(jié)點個數依然為2N-1.2.該線段樹深度可能會超過O(logn)。3.該線段樹區(qū)間定位所包含的線段樹節(jié)點個數可能超過O(logn)。但區(qū)間定位的結果依然是唯一的。小R給你這樣一個小R線段樹,每次詢問給定區(qū)間的區(qū)間定位個數。

? 這道題n和詢問個數都到了1e5,所以考慮nlogn的做法。

? 我們發(fā)現(xiàn)區(qū)間定位個數(答案)和完全被該區(qū)間包含的節(jié)點個數所相關。具體性質如下:區(qū)間定位個數(答案) = 2 * 區(qū)間長度 - 完全被該區(qū)間包含的節(jié)點個數。不難發(fā)現(xiàn)完全被該區(qū)間包含的節(jié)點個可以看作一個森林,而區(qū)間定位出的那些線段節(jié)點可以看作這些森林當中數的根。由于一個長度為l的根的樹的節(jié)點個數為 2 ? l ? 1,那么這個森林當中每有一棵樹,就會對“2 * 區(qū)間長度”這個總和上減去一,故滿足性質。那么我們將問題轉化為求完全被該區(qū)間包含的節(jié)點個數。

? 那么現(xiàn)在問題就是在所有的區(qū)間中,找到[l,r]所完全包含的區(qū)間。這是個二維偏序的問題。個人理解所謂二維偏序就是詢問許多向量中,比詢問的向量小的向量。由于這是偏序關系,所以不是任意兩個向量都可以比較大小。這里的定義是如果一個區(qū)間l,r,l<=l2,并且r>=r2,那么l,r小于l2,r2。具體做法就是一維排序,然后i從大到小(從小到大也可以,只不過這里dfs出來順序是從小到大的,那么就從大到小掃一遍),對于左端點在當前詢問左端點右側的區(qū)間,把其右側端點在樹狀數組里mark一下。然后查詢的時候,只查詢1到r被mark的值。這樣由于只統(tǒng)計了左端點在l右側的區(qū)間,并且區(qū)間的右端點被限制在1到r以內,所以所有區(qū)間都會被掃到。

? 感覺這種方法真奇妙。。

#include <cstdio> #include <algorithm> using namespace std;const int maxn=4e5+5; int n, m, cntseg, cntline, cntq, beg; int atree[maxn];struct Node{int lson, rson, mid; }node[maxn];struct Line{int l, r, id, ans;void set(const int &x, const int &y){ l=x, r=y; } }line[maxn], queries[maxn]; bool cmp1(const Line &x, const Line &y){return x.l==y.l?x.r<y.r:x.l<y.l; } bool cmp2(const Line &x, const Line &y){return x.id<y.id; }void build(int &now, int l, int r){line[cntline++].set(l, r);if (l==r) return;if (!now) now=++cntseg;scanf("%d", &node[now].mid);build(node[now].lson, l, node[now].mid);build(node[now].rson, node[now].mid+1, r); }inline int lowbit(int x){ return x&(-x); }void modify(int now){while (now<=n){++atree[now];now+=lowbit(now);} }int query(int now){int re=0;while (now){re+=atree[now];now-=lowbit(now);} return re; }int main(){scanf("%d%d", &n, &m);build(beg, 1, n);int l, r;for (int i=0; i<m; ++i){scanf("%d%d", &l, &r);queries[cntq].set(l, r);queries[cntq++].id=i;}sort(queries, queries+m, cmp1);int j=cntline-1;for (int i=m-1; i>=0; --i){//如果這個區(qū)間,它的左端點在查詢的左端點右邊//說明它對查詢的左端點是有效果的while (line[j].l>=queries[i].l){modify(line[j].r); --j;}queries[i].ans=2*(queries[i].r-queries[i].l+1)-query(queries[i].r);}sort(queries, queries+m, cmp2);for (int i=0; i<m; ++i)printf("%d\n", queries[i].ans);return 0; }

轉載于:https://www.cnblogs.com/MyNameIsPc/p/7657792.html

總結

以上是生活随笔為你收集整理的二维偏序 tree的全部內容,希望文章能夠幫你解決所遇到的問題。

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