乙個知識點不在一道題裡說是沒有靈魂的
線段樹是用來處理區間資訊的咯
但是往往因為需要4倍空間讓許多人退卻,而動態開點的線段樹就非常棒
彷彿只用2倍就可以咯
指標儲存位置,即節點資訊,是很舒適的,所以用指標動態開點就更棒
《永無鄉題面》
這個題哈,我剛開始學線段樹合併時慣例懵,
而且我發現……網上的題解有簡短甚至偷懶的,於是我很廢了,去問神犇
下面就是,比較清楚的題解
首先我們會發現這個題像乙個,圖論?
但是並不是,因為他問的並不是圖的問題(像最短路?),而是聯通性,和排名下標,就不用建圖
so,分開考慮
1.聯通性:dfs的是想岔了,冰茶几(並查集)適合維護這個-----> o(logn)
2.排名下標:
平衡樹,不會合併(哭笑不得)
線段樹,不錯,如果用權值線段樹就可以查排名咯
權值線段樹,類似於桶排序,用下標存數,每個節點存的是從l到r的數個數然後就是合併的操作(這個去專門學也好),用不空的節點直接代替空的節點,把不空的公共節點值相加這樣乙個數的排名就是左面的節點中個數加一
自帶二分,非常快
另外再說一句,我用指標的new函式了,所以慢死,我從大佬們處得知指標要與結構體陣列一塊用,達到既美觀直觀又快的效果
結果:
#include#include#include#define n 100010using namespace std;
struct xds
};xds *root[n];
int itd[n];
void build(xds *&rt,int l,int r)
void add(xds *&rt,int l,int r,int v)
int mid=(l+r)/2;
if(v<=mid)
else
if(rt->lid!=null)
rt->dat+=rt->lid->dat;
if(rt->rid!=null)
rt->dat+=rt->rid->dat;
}inline void add(xds *&rt,int v)
int kth(xds *rt,int k)
if(rt->lid!=null&&rt->lid->dat>=k)
else if(rt->rid!=null)
}return n;
}xds* mmerge(int l,int r,xds *a,xds *b)
int fa[n];
int faind(int x)
return fa[x];
}int isn,bn;
void prerun()
}void unity(int x,int y)
}int main()
char ch[3];
scanf("%d",&a);
for(int i=1;i<=a;i++)
else
}return 0;
}
線段樹動態開點
為了降低權值線段樹的空間複雜度,可以不直接建出整棵線段樹的結構,而是在最初只建立乙個根節點,當需要訪問某棵為建立的子樹的時候,再建立代表這個子樹的節點。動態開點的線段樹用變數記錄左右節點的編號。值域為1 n的動態開點線段樹在m次單點修改後,節點規模為o mlogn 例題 p1908 逆序對 這題n最...
線段樹 動態開點
在一些計數問題中,線段樹用於維護值域 一段權值範圍 這樣的線段樹也稱為權值線段樹。為了降低空間複雜度,我們可以不建出整棵線段樹的結構,而是在最初只建立乙個根節點,代表整個區間,當需要訪問線段樹的某棵子樹 某個子區間 時,再建立代表這個子區間的節點。採用這種方法維護的線段樹稱為動態開點的線段樹。動態開...
BZOJ 4756 線段樹合併(線段樹)
思路 1.最裸的線段樹合併 2.我們可以觀察到子樹求乙個東西 那我們直接dfs序好了 入隊的時候統計一下有多少比他大的 出的時候統計一下 減一下 搞定 線段樹合併 by siriusren include include include using namespace std const int n...