NKOJ P2670 動態區間第K小數 分塊

2021-08-21 08:40:40 字數 2491 閱讀 3626

這道題呢其實也是乙個毒瘤…調了好久的**這道題…讓我意識到自己對於stl的很多東西都還是不熟(比如low

erbo

un

dlower bound

lowerb

ound

,於是我就手寫了乙個二分查詢)。

當然這道題還是確實讓我見識到了分塊的強大…動態區間第k

kk小數普遍的方法就是各種主席樹,樹套樹來做,但是分塊就除去了寫各種樹產生的不必要的麻煩(其實這算是我第一次真正寫分塊中間有很多地方細節最開始都沒有注意)。

正題 :

首先我們先考慮一下將已知的陣列a[]

aa[

]按照常規操作進行分塊:將a[]

aa[

]分為n

\sqrt

n​塊,每塊n

\sqrt

n​個數,然後我們就將每塊中的數字從小到大排序得到乙個新陣列b[]

bb[

]。我們用a[]

aa[

]記錄原數列,b[i

]b[i]

b[i]

記錄排序後第i

ii塊的數字。

分好塊了,接下來讓我們考慮一下修改。由於題意的修改是直接將原數列的某乙個數修改為新數,所以我們直接a[x

]=

ya[x]=y

a[x]=y

即可,但是與此相對應的b[]

bb[

]也需要修改,所以我們就用二分查詢找到原a[x

]a[x]

a[x]

在b []

bb[

]中對應的b[l

oc

]b[loc]

b[loc]

,進行修改b[l

oc]=

yb[loc]=y

b[loc]

=y。但是這樣修改後我們發現原來排好序的有序數列有可能被打亂了,這個時候我們就只需要重新排序即可。

考慮完了修改,就再來考慮一下查詢[x,

y]

[x,y]

[x,y]。

如果[ x,

y]

[x,y]

[x,y

]位於同乙個塊當中,那麼我們就只需要暴力列舉即可,問題其實在於[x,

y]

[x,y]

[x,y

]位於多個塊當中的時候我們應該如何操作。考慮一下二分答案:我們不妨二分乙個mid

midmi

d值,並且假設我們已經知道每個塊當中有多少個數比mid

midmi

d小,於是我們就可以得到:若[x,

y]

[x,y]

[x,y

]中比mid

midmi

d小的數字有k−1

k-1k−

1個,那麼此時的mid

midmi

d就是第k

kk小數,輸出即可,如果比mid

midmi

d小的數字大於k−1

k-1k−

1個,那我們就減小mid

midmi

d,如果大於,我們就增大mid

midmi

d。那麼問題來了,我們應該如何統計塊中比mid

midmi

d小的數字有多少個呢?注意到,我們前面已經維護了每個塊的有序性,所以我們就只需要二分查詢進行確定mid

midmi

d在每乙個塊當中應佔的位置即可。

#include #include #include #include #include #define db double

#define sg string

#define ll long long

using namespace std;

const int max=5e4+5;

const int mod=1e9+7;

const int inf=1e18;

char ch[3];

ll n,m,s,snum,a[max],b[max],l[max],r[max];

inline int read()

while(ch>='0'&&ch<='9')

return f?-x:x;

}inline void write(int x)

void update()

ll find(ll x,ll num) else if (b[mid]=l[k]&&b[get-1]==b[get])cnt=cnt+get-l[k];

} }return cnt;

}ll getans() else

} write(left),putchar('\n');

}int main()

for(i=1;i<=n;i++)

for(i=1;i<=snum;i++)r[snum]=n;

for(i=1;i<=snum;i++)

for(i=1;i<=m;i++) else

} return 0;

}

主席樹 動態區間第k小

模板題在這裡洛谷2617。閱讀本文需要有主席樹的基礎,也就是通過區間kth的模板題。靜態整體kth sort一下找第k小,時間複雜度 o nlogn 動態整體kth 權值線段樹維護一下,時間複雜度 o nlogn 靜態區間kth 主席樹維護,時間複雜度 o nlogn 動態區間kth 就是本次的標題...

區間第k大

問題描述 給定乙個序列,每次詢問序列中第l個數到第r個數中第k大的數是哪個。輸入格式 第一行包含乙個數n,表示序列長度。第二行包含n個正整數,表示給定的序列。第三個包含乙個正整數m,表示詢問個數。接下來m行,每行三個數l,r,k,表示詢問序列從左往右第l個數到第r個數中,從大往小第k大的數是哪個。序...

區間第k大

歸併樹 include include include include include include include include include include include define ll long long define max x,y x y x y define min x,y ...