正睿集訓2021 模擬賽3

2022-05-23 21:00:08 字數 3984 閱讀 8206

題目描述

給定乙個序列 \(a\),保證 \(a_i\) 互不相同。你需要重新排列 \(a\),使得 \(a\) 中任意兩個相鄰位置都包含乙個奇數和偶數。對於每個數,它的代價是\(|\)初始位置減重排後的位置\(|\) 。請輸出保證總代價最小的前提下,字典序最小的 \(a\)

\(1\leq n\leq 10^5,1\leq a_i\leq 10^9\)

題目描述

定義 \(f(n)\) 表示將 \(n\) 劃分為若干 \(m\) 的非負整數次冪的和的方案數。定義 \(g(n)\) 表示 \(k\) 個 \(f(n)\) 的卷積。給定 \(n,m,k\),求出 \(\sum_^n g(i)\) 對 \(1e9+7\) 取模後的結果。

\(0\leq n\leq 10^,2\leq m\leq 10^,1\leq k\leq20\)

解法

\(k=1\) 的情況,此時 \(f_m\) 可以使用組合意義生成函式卷積:

\[f(n)=[x^n]\sum_^\infty\frac}

\]有乙個小 \(\tt trick\),因為要求係數和,所以可以把原來的多項式再乘以 \(\frac\) 就可以直接求 \([x^n]\)

然後問題變成了求第 \(n\) 項的係數,假如我們加入 \(m^i\) 的物品,那麼起作用的只有 \(i=n\mod m^i\) 這些位置的值。所以不難設計出狀態,設 \(f(i,j)\) 表示加入了 \(i\) 件物品,容量是 \(jm^i+(n\% m^i)\) 的方案數(有一點點不嚴謹但是沒關係),轉移不難寫出:

\[f(i,j)=\sum_^j f(i-1,xm+bit(n,i-1))

\]其中 \(bit(n,i-1)\) 表示 \(n\) 在第 \(i-1\) 為上的值,因為 \(jm^i+(n\%m^i)\) 可以從 \(xm^i+(n\%m^i)\) 轉移而來,也就是 \(xm\cdot m^+(n\% m^)+bit(n,i-1)\)

這個東西第二維很大,又是那個神奇的套路!我們假設 \(f(i,j)\) 是 \(j\) 的 \(i\) 次多項式,然後歸納證明這個結論。原因就蘊含在轉移中,\(f(i-1,xm+bit(n,i-1))\) 是乙個關於 \(xm+bit(n,i-1)\) 的多項式,也就是關於 \(x\) 的 \(i-1\) 次多項式。那麼我們把這些多項式求了乙個字首和,所以是乙個 \(i\) 次多項式。

所以用 \(o(i^3)\) 求出 \(o(i)\) 個點值就可以 \(o(i^2)\) 插值求出這個多項式,因為第一維超級小所以複雜度是對的。

那麼如果 \(k>1\) 呢?那麼我們把 \(m^i\) 的物品做若干次就行了,轉移有點小修改,但是大體思路是一樣的,時間複雜度 \(o(k^3\log^3_mn)\)

題目描述

定義乙個括號序列是合法的,當且僅當它的任意乙個字首滿足(的數量不小於)的數量,且整個序列中左括號和右括號的數量相等。(不要以為這句話沒有用哦,其實它是乙個提示)

定義乙個括號序列是好的,當且僅當存在兩個並為整個序列的子串行,使得每個子串行都是合法的括號序列。現在給你乙個長為 \(n\) 的括號序列,有 \(m\) 次詢問,每次詢問給定乙個區間 \([l,r]\),你需要求出有多少個子區間是好的括號序列。

\(n,m\leq3e5,1\leq l\leq r\leq n\)

解法

我竟然都能把結論猜出來,但是結論後面的維護也超難的好伐。

結論:乙個好的括號序列等價於,把左括號看做 \(2\) 右括號看做 \(-1\),要求每個字首都 \(\geq 0\);把右括號看做 \(2\) 左括號看做 \(-1\),要求每個字尾都 \(\geq0\)

考慮證明,必要性顯然。充分性可以構造方案證明。具體來說,我們考慮先構造出乙個滿足(的位置為2或1,)的位置為-2或-1的序列,使得它們和為0,且任意字首和。這個可以考慮將(當成2,)當成-1得到的序列,每次將最後乙個還沒減小過的括號-1,直到序列總和為0,顯然這樣是可以達到的,並且任意時刻仍然滿足字首和和字尾和的限制。得到這個序列以後,可以將2和-2當成兩個子串行的公共部分,奇數個的1和奇數個的-1分配給第乙個序列,偶數個的1和偶數個的-1分配給第二個序列,這樣兩個序列字首和的差的絕對值任意時刻不會》1,又知道他們總和,因此顯然是合法的方案。

考場上我寫的是暴力判斷每個區間是否是好的,然後二維數點,時間複雜度 \(o(n^2\log n)\)

這時候要仔細觀察限制,字首\(\geq0\)和字尾\(\geq0\) 其實是兩個相對獨立的限制條件。現在的思路就是解決這兩個限制

考慮字尾 \(\geq0\) 這個限制條件,固定乙個點,那麼它延伸到的範圍是固定的,而且延伸到的地方合法未延伸到的地方不合法,這就是乙個很好的性質了,可以預處理 \(b[i]\) 表示 \(i\) 最多向左延伸多少,這個就相當於找字首和陣列第乙個比它大的數,直接用單調棧做就可以了。

字首 \(\geq0\) 這個限制可以通過離線解決。我們讓右端點從左往右掃,考慮到答案是統計 \([l,r]\) 的子區間,有乙個騷操作:我們把貢獻記在左端點上,可以用線段樹去維護左端點的貢獻。

具體講一講怎麼離線,遇到左括號時,它是可以作為左端點的,那我們就啟用這個點。遇到右括號時,求 \([1,i]\) 的區間最小值,要刪去不合法的左端點。右括號可以作為右端點,所以我們把 \([b[i],i]\) 中的啟用左端點貢獻\(+1\),詢問就直接區間查詢。

線段樹都是一些常規操作,具體要維護什麼可以掃一眼我的**。時間複雜度 \(o(n\log n)\)

#include #include #include #include using namespace std;

const int m = 300005;

const int inf = 1e9;

#define ll long long

#define pii pairint read()

int n,m,top,a[m],b[m],p[m];char s[m];

int mi[4*m],fl[4*m],pos[4*m],pd[4*m];ll sum[4*m],tag[4*m],ans[m];

struct node

pii get(int i,int l,int r,int l,int r)//求出最小值

void upd(int i,int l,int r,int l,int r,int f)//區間加

int mid=(l+r)>>1;down(i);

upd(i<<1,l,mid,l,r,f);

upd(i<<1|1,mid+1,r,l,r,f);

up(i);

}void add(int i,int l,int r,int l,int r)//區間更新答案

int mid=(l+r)>>1;down(i);

add(i<<1,l,mid,l,r);

add(i<<1|1,mid+1,r,l,r);

up(i);

}ll ask(int i,int l,int r,int l,int r)//區間問答案

int main()

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

sort(q+1,q+1+m);

for(int i=0;i<=4*n;i++) mi[i]=inf;

for(int i=1,j=1;i<=n;i++)

if(s[i]==')')

add(1,1,n,b[i],i);//加答案

} while(j<=m && q[j].r<=i)

}for(int i=1;i<=m;i++)

printf("%lld\n",ans[i]);}/*

字首:( 2 ; ) -1 >=0

字尾:) 2 ; ( -1 >=0

*/

noip 模擬賽 正睿oi(一) 給

給 ca.pas c cpp 背景描述 對於任意1 k n,求有多少個左右區分的恰有k個葉子節點的二叉樹,滿足對於每個節點要麼沒有葉子節點要麼有兩個節點,同時不存在乙個葉子節點,使得根到它的路徑上有不少於m條向左的邊。你只需要求出答案對998244353取模的結果。輸入格式 輸入共一行,兩個正整數m...

2019正睿金華集訓 0804總結

今天感受了b班考試的難度,果然好難,接近爆蛋,暴力分都不太好拿。考試歷程 先看了一下三個題面,發現就第二題的暴力好寫一點,隨後又想到了並查集,然後去寫t2,過了樣例然後我就不管了 以為自己可以拿到暴力分 t3這道題我只想說,貌似除了暴力我好像也寫不了,於是我寫了乙個大暴力,由於是輸出方案,評測機是s...

正睿17 2天集訓總結TOT

暑期開始踏入c班集訓的時候,覺得c班的考試和講課好難啊。但一對比正睿的b c班,頓時無話可說。在海亮考試勉勉強強不會掉出前面的一半,到了正睿就是勉勉強強能不排上倒數 雖然最後一次就是倒數了 b班的速度太快,還是c班注重一些基本的模板和概念,更加具體。題目質量很高,ppt上的題很少見但是很經典,學到的...