區間帶修改的第 \(k\) 大需要用帶修改主席樹。
如果用平常的主席樹的效率是多少呢?
查詢 \(o(logn)\),暴力修改 \(o(nlogn)\),時間不支援
那麼就需要平衡一下兩者的時間複雜度
我們用樹狀陣列套主席樹,每次查詢把 \(logn\) 個 \(rt\) 取出來,\(l-1\) 和 \(r\) 的 \(sum\) 相減一下,在值域進行 \(logn\) 的遍歷,時間複雜度 \(o(nlog^2n)\)
int query(int l,int r,int k)
else
}
每次修改在樹狀陣列上,遍歷到乙個點就 \(update\),動態開點
void update(int &now,int l,int r,int x,int v)
void add(int x,int v)
每次修改要新開一條鏈上 \(logn\) 個結點,一共執行 \(logn\) 次,空間複雜度 \(o(nlog^2n)\)
不難證明時間複雜度 \(o(nlog^2n)\)
\(code\ below:\)
#include #define lowbit(x) ((x)&(-(x)))
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],mp[maxn<<1],cnt;
int t[maxn],lt[maxn],rt[maxn],l[maxn*400],r[maxn*400],sum[maxn*400],tot,cnt1,cnt2;
struct queryq[maxn];
inline int read()
while(isdigit(ch))
return (f==1)?x:-x;
}void update(int &now,int l,int r,int x,int v)
void add(int x,int v)
int query(int l,int r,int k)
else
}int main()
sort(mp+1,mp+cnt+1);
cnt=unique(mp+1,mp+cnt+1)-mp-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(mp+1,mp+cnt+1,a[i])-mp,add(i,1);
for(int i=1;i<=m;i++)
else
} return 0;
}
先用樹狀陣列求一下總的逆序對
然後每次就減去當前在 \([1,pos[x]-1]\) 中大於 \(x\) 的數的個數和當前在 \([pos[x]+1,n]\) 中小於 \(x\) 的數
帶修改主席樹即可,時間複雜度 \(o(nlog^2n)\),空間複雜度 \(o(nlog^2n)\)
\(code\ below:\)
#include #define ll long long
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int maxn=100000+10;
int n,m,a[maxn],pos[maxn];ll ans;
int t[maxn],lt[maxn],rt[maxn],l[maxn*400],r[maxn*400],sum[maxn*400],tot,cnt1,cnt2;
inline int read()
while(isdigit(ch))
return (f==1)?x:-x;
}namespace unorder_pair
int sum(int x)
}t;ll solve()
return ans;
}}void update(int &now,int l,int r,int x,int v)
void add(int x,int v)
int query(int l,int r,int v,int sta)
for(int i=1;i<=cnt1;i++) lt[i]=r[lt[i]];
for(int i=1;i<=cnt2;i++) rt[i]=r[rt[i]];
l=mid+1;
}else
for(int i=1;i<=cnt1;i++) lt[i]=l[lt[i]];
for(int i=1;i<=cnt2;i++) rt[i]=l[rt[i]];
r=mid;}}
return ans;
}int main()
return 0;
}
帶修改的主席樹
對於單點修改的主席樹,我們可以採用樹套樹來寫,原因 不會整體二分求帶修改的區間第k小。所以學習了一波 待修改的主席樹。真的是難寫,或者說碼量有點大。不過和三維偏序cdq分治相比其實差不了多少,但是cdq終究比樹套樹快而且空間消耗小。兩者都很不錯!經典題,但是對於我這個根本不懂樹套樹的人來說是有點難度...
Data 帶修改的主席樹 樹狀陣列套主席樹
樹狀陣列套主席樹 樹狀陣列的每個節點維護的是一段區間,我們將每個區間構造成一棵線段樹,這時候如果我們要修改乙個值,只需要修改logn個節點即可,時間複雜度為log 2 n 樹狀陣列維護的區間是數的個數n 離散化時是把所有數 包括要修改的數 全部離散化 1.修改 在修改之前,我們應先把序列裡原來的值在...
主席樹學習筆記
問題 給定乙個n個數的序列,q次詢問第x個數到第y個數中的第k最值。我們假定是第k小。為了使討論更加簡便,我們假定序列的每個數都是不大於n的正整數。當然一般題目中元素範圍很大,但是可以用離散化預處理來做到這一點。考慮乙個比較高階的做法 令g i j 為前i個數中,值為j的數的個數。很容易用o n 2...