分析:線段樹合併人生第一題。
網上的題解我都沒看懂……我自己講一下好了
線段樹合併就是把兩棵權值線段樹合併到一棵
那怎麼合併呢?
假設有這麼兩棵樹:
乙個結點代表一段值域區間有幾個數,那麼可以看出合併後應該是這樣的
然後具體步驟就是找到乙個結點,如果乙個結點一棵樹上有一棵樹上沒有,那麼直
接返回那個結點的編號,否則兩個值域的和相加,遞迴至左兒子和右兒子
每次合併的複雜度為兩棵線段樹的點數相加
這道題可以算出左兒子的逆序對個數,右兒子的逆序對個數,然後求出 \((x,y)\) 的對數, $x\in $ 左兒子, $y\in $ 右兒子
每次記錄一下 \(sum\),在每次合併的時候 \(sum[lson[x]]\times sum[rson[y]]\) 和 \(sum[rson[x]]\times sum[lson[y]]\) 中取個最小值算進答案的貢獻就可以了(不懂可以自己畫圖或看**理解一下)
\(code\ below:\)
#include #define ll long long
using namespace std;
const int maxn=200000+10;
int n,l[maxn*24],r[maxn*24],sum[maxn*24],cnt;
ll ans,num1,num2;
inline int read()
while(isdigit(ch))
return (f==1)?x:-x;
}void update(int &now,int l,int r,int x)
void merge(int &x,int y)
sum[x]+=sum[y];
num1+=(ll)sum[r[x]]*sum[l[y]];
num2+=(ll)sum[l[x]]*sum[r[y]];
merge(l[x],l[y]);
merge(r[x],r[y]);
}void dfs(int &x)
else update(x,1,n,val);
}int main()
分析:考慮樹上查分。這次權值線段樹維護最多救濟糧的編號 \(val\) 和 最多救濟糧的個數 \(sum\),在葉子節點更新一下,最後 \(pushup\) 一下
\(code\ below:\)
#include using namespace std;
const int maxn=100000+10;
const int size=100000;
int n,m,ans[maxn],rt[maxn],l[maxn*80],r[maxn*80],val[maxn*80],sum[maxn*80],cnt;
int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn];
inline int read()
while(isdigit(ch))
return (f==1)?x:-x;
}inline void add(int x,int y)
void dfs1(int x,int f)
void pushup(int now)
void merge(int &x,int y,int l,int r)
if(l == r)
int mid=l+r>>1;
merge(l[x],l[y],l,mid);
merge(r[x],r[y],mid+1,r);
pushup(x);
}void dfs(int x,int f)
ans[x]=val[rt[x]];
}int main()
while(isdigit(ch))
return (f==1)?x:-x;
}inline void add(int x,int y)
void pushup(int now)
void update(int &now,int l,int r,int x)
if(x <= mid) update(lson,l,mid,x);
else update(rson,mid+1,r,x);
pushup(now);
}void merge(int &x,int y,int l,int r)
if(l == r)
merge(l[x],l[y],l,mid);
merge(r[x],r[y],mid+1,r);
pushup(x);
}void dfs(int x,int f)
an[x]=ans[rt[x]];
}signed main()
{ n=read();
int x,y;
for(int i=1;i<=n;i++) a[i]=read();
for(int i=1;i搞了乙個下午線段樹合併,還是很有成就感滴!
線段樹合併學習筆記
線段樹合併對一整個樹做完時間空間複雜度是n log nn log n nlog n的,套點其他什麼東西複雜度就上去了 動態開點的話注意 空間 樹上主席樹啟發式合併的話不 空間是兩個log的,容易被卡,比如這題 我就被卡了 悲 當然線段樹合併貌似總是可以被spl ay splay spla y啟發式合...
線段樹合併學習筆記
就是兩顆線段樹合成乙個線段樹 那合成的線段樹是適合所有線段樹嗎 當然不是,是動態開點線段樹 這裡建n個節點的時候,每個節點建一棵樹 而且要按照一定的形態建立一條鏈 就是說如果最終形態是有n個數字的樹,那你初始化的那一條鍊子一定是這顆樹上扣下來的 這樣才方便合併 最重要的操作 流程 如果x和y有一顆樹...
線段樹合併 學習筆記
權值線段樹 動態開點線段樹 有時候我們需要對權值線段樹進行合併操作。然後就用到了線段樹合併。一般是有很多棵線段樹,然後需要將其中的兩棵合併起來。其實方法很簡單呢。就是分三種情況討論一下。假設現在要將線段樹a和線段樹b合併。並且a成為合併之後的線段樹。如果a有當前子樹,而b沒有,那麼返回a的當前子樹 ...