Old Problem 帶修改的kth

2021-08-01 18:05:43 字數 1846 閱讀 9487

這是乙個經典問題

n個數的數列a[1…n]

q次操作 :

1 l r x 區間[l,r] 加 x

2 l r k 詢問區間[l,r] 第k大的數

0n<105

,256mb 4 seconds

這個問題陳老師在一篇**中給了3種方法

我選擇了實現比較簡單的 二分+分塊

#include
#include

#include

using namespace std;

const int maxn=1e5+5,num=2e3;

int a[maxn],sa[maxn],tag[num],n,m,num;

inline void build()

for(int i=0;i<=n;i++)

for(int i=0;isort(sa+i*num,sa+i*num+num);

}}inline void change(int l,int r,int t)

if(r/num==n/num) return ;

for(int i=l/num*num;i*num+num;i++)

sort(sa+l/num*num,sa+r/num*num+num);

return ;

}for(int i=l/num+1;ifor(int i=l;i*num+num;i++)

for(int i=l/num*num;i*num+num;i++)

sort(sa+l/num*num,sa+l/num*num+num);

for(int i=r/num*num;i<=r;i++)

if(r/num==n/num) return ;

for(int i=r/num*num;i*num+num;i++)

sort(sa+r/num*num,sa+r/num*num+num);

}inline int query(int l,int r,int qn)

}return cnt;

}for(int i=l;i*num+num;i++)

}for(int i=r/num*num;i<=r;i++)

}for(int i=l/num+1;i*num,sa+i*num+num,qn-tag[i])-(sa+i*num);

}return cnt;

}inline int getkth(int l,int r,int k)

return top;

}int main()

else}}

return

0;}第一次寫分塊,寫了個驗證程式,也附上吧

資料生成

#include

#include

#include

const int maxn=1e5+5;

const int t=10;

int a[maxn];

int main()

}return

0;}

暴力驗證

#include

#include

using

namespace

std;

const

int maxn=1e5+5;

int a[maxn],b[maxn],n,m;

int main()

if(op==1)else}}

return

0;}

帶修改區間k大

看了好久,後來自己想了一下。大概就是說因為原來的寫法下要修改的代價太大了,所以套上乙個樹狀陣列使每顆主席樹存特定幾個位置上的權值。平均一下修改和詢問的代價。include include include define n 2200001 using namespace std int n,m,tot...

帶修改的區間第k小 樹狀陣列套主席樹

題目鏈結 對乙個序列進行兩種操作 對於不待修改的區間第k kk小,我們可以用主席樹完成。我們來看看只用主席樹如何完成帶修改的區間第k kk小。對於每次修改,我們都需要把當前位置及以後的主席樹都進行修改。因此每次修改的時間複雜度為o n log n o nlog n o nlog n 空間增加o n ...

帶修改的主席樹

對於單點修改的主席樹,我們可以採用樹套樹來寫,原因 不會整體二分求帶修改的區間第k小。所以學習了一波 待修改的主席樹。真的是難寫,或者說碼量有點大。不過和三維偏序cdq分治相比其實差不了多少,但是cdq終究比樹套樹快而且空間消耗小。兩者都很不錯!經典題,但是對於我這個根本不懂樹套樹的人來說是有點難度...