總算是把動態求區間第k個數的演算法看明白了。
在主席樹的基礎上,如果有修改操作,則要通過套樹狀陣列來實現任意區間求第k小的問題。
剛開始看不明白什麼意思,現在有一點理解。樹狀陣列的每個元素是乙個線段樹,來維護修改後的前字尾和,樹狀陣列能在log時間內更整個陣列,現在用相同的方式更新整個線段樹陣列,每次更新乙個點時,要更新這個點代表的整個線段樹。同樣的,求和時用乙個use陣列記錄所要更新的點的下標,每次求不同線段樹的同一位置的和。
靜態初值不要用來初始化樹狀陣列。
考慮到字首和,我們通過樹狀陣列來優化,即樹狀陣列套主席樹,每個節點都對應一棵主席樹,那麼修改操作就只要修改logn棵樹,
o(nlognlogn+mlognlogn)時間是可以的,但是直接建樹要nlogn*logn(10^7)會mle。
我們發現對於靜態的建樹我們只要nlogn個節點就可以了,而且對於修改操作,只是修改m次,每次改變倆個值(減去原先的,加上現
在的)也就是說如果把所有初值都插入到樹狀陣列裡是不值得的,所以我們分兩部分來做,所有初值按照靜態來建,記憶體o(nlogn),
而修改部分儲存在樹狀陣列中,每次修改logn棵樹,每次插入增加logn個節點o(m*logn*logn+nlogn)。
//#pragma comment(linker, "/stack:1024000000,1024000000")
#include#include#include#include #include#include#include#include#include#include#include#includeusing namespace std;
#define eps 1e-8
#define pii pair#define inf 0x3f3f3f3f
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
#define ll long long int
#define mod 1000000007
#define maxn 60005
#define maxm 2500005
int m,n,nn,tot;
int a[maxn],f[maxn],t[maxn],s[maxn];
int sum[maxm],l[maxm],r[maxm];
int use[maxn];
int h(int x)
void update(int pr,int lx,int rx,int v,int k)
else
}void build(int rt,int lx,int rx)
int lowbit(int x)
int sum(int x)
void add(int x,int v,int k) }
int query(int l,int r,int k)
else
}return f[lx];
}char op[5];
int q[10005][4],t;
int main()
nn=n;
for(int i=1;i<=m;i++)
else
}sort(f+1,f+1+nn);
nn=unique(f+1,f+1+nn)-f-1;//離散化線段樹,並去重
tot=0;
t[0]=0;
build(0,1,nn);
for(int i=1;i<=n;i++)
for(int i=1;i<=n;i++) s[i]=t[0];
// int l,r,k,x;
for(int i=1;i<=m;i++)
else}}
return 0;
}
zoj 2112 主席樹套樹狀陣列
現在把主席樹的原理給弄清楚了,從i 1開始,每次新插入乙個數,就為他建一棵線段樹 當然第一次i 0的時候是建一棵空樹 線段樹裡面儲存的是1 i的樹的位置情況 簡單來說,如果有m個樹,則每棵線段樹都是範圍為1 m的,至於1 i沒有m個那就先讓它空著不管,我只負責1 i裡面的數的位置情況插入到線段樹裡面...
zoj 2112 主席樹套樹狀陣列 優化
題解思路 如果直接對原來的陣列建立主席樹套樹狀陣列的空間複雜度是 n m log n m log n m 這樣明顯 那麼我們可以對原來的數組建主席樹模型,空間複雜度就是n logn,對m裡面的修改建主席樹套樹狀陣列空間複雜度是m logm logm明顯小了很多。include define lson...
Zoj 2112 線段樹套Treap
樹套樹入門題 樹套樹空間複雜度分析 維護乙個長度為n的序列,線段樹的結點數一般為4n,而treap則是對於每乙個元素 包括重複出現的 都需要乙個空間,那麼第1層的所需要的空間為 1 n 第二層為 2 n 2 所以其實為o h n.那麼所需的空間為o nlog n 但在實際運用中,所形成的線段樹往往不...