GDOI2018模擬8 12 區間第k小

2021-08-07 05:18:07 字數 1551 閱讀 7547

orz 資料結構 根號演算法講師

首先如果詢問可以離線怎麼做?

乙個顯然的思路就是莫隊+資料結構直接做,但是這樣是o(

nn√logn)

的 實測資料無梯度乙個點都跑不過qwq

但是我們觀察莫隊,我們最壞可能有nn

−−√ 次插入,但只有n次詢問,我們考慮平衡一下這兩個複雜度

觀察到值域也只有n,所以我們可以同時對值域分塊

我們維護fi表示當前區間中值在值域第i塊的出現次數<=w的數有多少個,再維護乙個di表示i這個數出現了多少次,那麼就可以做到o(1)插入或刪除

然後對於每次詢問我們暴力掃瞄所有塊,找到答案屬於哪個塊中,然後再暴力進入這個塊中查詢

這樣就做到總複雜度o(nn

−−√

nn−−

√ )預處理

再維護乙個gi,j表示前i塊數j出現了多少次,這個也可以o(nn

−−√ )預處理

那麼對於每次詢問,我們把多餘出來的部分維護乙個di,含義和上文相同,然後把d和f、d和g合併得到和上文功能相同的陣列,按照上文的做法就可以通過此題

總複雜度依舊是o(nn

−−√ )

#include 

#include

#include

#define fo(i,a,b) for(int i=a;i<=b;i++)

using namespace std;

const int n=1e5+5,m=333;

int n,q,ty,le,ri,k,u,v,ans,w,sz,l[m+5],r[m+5],a[n],b[n];

int d[n],vis[m+5],g[m+5][n],f[m+5][m+5][m+5];

intread()

int get_ans(int u,int v)

now+=vis[i];

}if (!sg) return n;

int st=l[sg],ed=r[sg];

if (sg==1) st=0;

if (sg==sz) ed=n-1;

fo(i,st,ed)

}int main()

fo(i,1,sz) }}

fo(i,0,n-1) d[i]=0;

for(;q;q--)

fo(i,1,sz) if (l[i]<=ri&&r[i]>=ri)

if (u+1>=v)

ans=get_ans(0,0);

printf("%d\n",ans);

fo(i,le,ri) d[a[i]]=0;

continue;

}fo(i,1,sz) vis[i]=f[u+1][v-1][i];

fo(i,le,r[u])

fo(i,l[v],ri)

ans=get_ans(u,v-1);

fo(i,le,r[u]) d[a[i]]=0;

fo(i,l[v],ri) d[a[i]]=0;

printf("%d\n",ans);

}}

GDOI2018模擬7 8 質數

將1 n分成盡可能小的集合,使得每個集合的元素均為質數 乙個數n n 6000 第一行乙個數m表示分成幾塊 第二行n個1 m的數表示每個數分到哪一塊 2 1 2 2 1 1 1 1 2 這題很有趣 我們知道有個哥德 猜想 任意乙個足夠大的偶數可以分成兩個質數的和 由於目前人類沒有證明出它是錯的,而且...

GDOI2018模擬8 11 決戰

聽說暴力狀壓可以過?然而我常數不好只有90分 考慮普通的狀壓,f i s j 表示當前填到第i行,第i行的狀態為s,用了j個哲學 家的方案數 我們把最後一維看做多項式,用x j的係數表示答案 咦?模數是998244353哦,那我們是不是可以用ntt加速呢?如果我們求出對於所有wi 答案的多項式的點值...

GDOI2018模擬8 14 神奇的矩陣

輸出一行表示答案 3 3 2 1 2 3 4 5 6 7 8 9 真是神奇的一道題 為了避免絕對值的影響,讓每個數字從小到大加入,對於每個數字考慮貢獻 設f i j 表示以 i,j 為左上角的k k的矩陣中有數的個數 那麼乙個數在加入時,所有包括它的k k矩陣的f的和,就是這個數對答案做的正貢獻 那...